From adf17c427fb99b021fd3ab29a62d5aaece9e2268 Mon Sep 17 00:00:00 2001 From: Shell Date: Wed, 29 Mar 2023 18:31:05 +0800 Subject: [PATCH] [bsp] rpi 4b smart & rtos fixups (#7114) * [bsp] rpi 4b smart & rtos fixups * [format] remove spaces & modify readme * [bsp] update rpi4b readme --- bsp/raspberry-pi/raspi4-64/.config | 355 +++++--------- bsp/raspberry-pi/raspi4-64/Kconfig | 3 +- bsp/raspberry-pi/raspi4-64/README.md | 122 +++-- bsp/raspberry-pi/raspi4-64/SConstruct | 16 +- .../raspi4-64/applications/SConscript | 7 +- bsp/raspberry-pi/raspi4-64/driver/SConscript | 9 - bsp/raspberry-pi/raspi4-64/driver/board.c | 172 ------- bsp/raspberry-pi/raspi4-64/driver/board.h | 30 -- bsp/raspberry-pi/raspi4-64/driver/drv_eth.h | 216 --------- bsp/raspberry-pi/raspi4-64/driver/drv_gpio.c | 187 -------- bsp/raspberry-pi/raspi4-64/driver/drv_sdio.h | 268 ----------- bsp/raspberry-pi/raspi4-64/driver/mbox.h | 188 -------- bsp/raspberry-pi/raspi4-64/driver/raspi4.h | 167 ------- .../raspi4-64/{driver => drivers}/Kconfig | 51 +- bsp/raspberry-pi/raspi4-64/drivers/SConscript | 19 + bsp/raspberry-pi/raspi4-64/drivers/board.c | 245 ++++++++++ bsp/raspberry-pi/raspi4-64/drivers/board.h | 36 ++ .../raspi4-64/drivers/drv_dsi_touch.c | 243 ++++++++++ .../raspi4-64/{driver => drivers}/drv_eth.c | 441 +++++++++--------- bsp/raspberry-pi/raspi4-64/drivers/drv_eth.h | 225 +++++++++ bsp/raspberry-pi/raspi4-64/drivers/drv_gpio.c | 439 +++++++++++++++++ .../raspi4-64/{driver => drivers}/drv_gpio.h | 20 +- .../raspi4-64/drivers/drv_gtimer.c | 74 +++ bsp/raspberry-pi/raspi4-64/drivers/drv_hdmi.c | 353 ++++++++++++++ bsp/raspberry-pi/raspi4-64/drivers/drv_hdmi.h | 27 ++ .../raspi4-64/{driver => drivers}/drv_sdio.c | 255 ++++------ bsp/raspberry-pi/raspi4-64/drivers/drv_sdio.h | 253 ++++++++++ bsp/raspberry-pi/raspi4-64/drivers/drv_spi.c | 296 ++++++++++++ bsp/raspberry-pi/raspi4-64/drivers/drv_spi.h | 87 ++++ .../raspi4-64/{driver => drivers}/drv_uart.c | 108 +++-- .../raspi4-64/{driver => drivers}/drv_uart.h | 42 +- .../raspi4-64/{driver => drivers}/drv_wdt.c | 68 +-- .../raspi4-64/{driver => drivers}/drv_wdt.h | 3 +- .../raspi4-64/{driver => drivers}/mbox.c | 211 ++++----- bsp/raspberry-pi/raspi4-64/drivers/mbox.h | 180 +++++++ bsp/raspberry-pi/raspi4-64/drivers/raspi4.h | 200 ++++++++ bsp/raspberry-pi/raspi4-64/link.lds | 168 +++---- bsp/raspberry-pi/raspi4-64/link_smart.lds | 109 +++++ bsp/raspberry-pi/raspi4-64/rtconfig.h | 107 +++-- bsp/raspberry-pi/raspi4-64/rtconfig.py | 6 +- bsp/raspberry-pi/raspi4-64/tools/config.txt | 5 + bsp/raspberry-pi/raspi4-64/tools/u-boot64.bin | Bin 0 -> 516040 bytes 42 files changed, 3663 insertions(+), 2348 deletions(-) delete mode 100644 bsp/raspberry-pi/raspi4-64/driver/SConscript delete mode 100644 bsp/raspberry-pi/raspi4-64/driver/board.c delete mode 100644 bsp/raspberry-pi/raspi4-64/driver/board.h delete mode 100644 bsp/raspberry-pi/raspi4-64/driver/drv_eth.h delete mode 100644 bsp/raspberry-pi/raspi4-64/driver/drv_gpio.c delete mode 100644 bsp/raspberry-pi/raspi4-64/driver/drv_sdio.h delete mode 100644 bsp/raspberry-pi/raspi4-64/driver/mbox.h delete mode 100644 bsp/raspberry-pi/raspi4-64/driver/raspi4.h rename bsp/raspberry-pi/raspi4-64/{driver => drivers}/Kconfig (69%) create mode 100644 bsp/raspberry-pi/raspi4-64/drivers/SConscript create mode 100644 bsp/raspberry-pi/raspi4-64/drivers/board.c create mode 100644 bsp/raspberry-pi/raspi4-64/drivers/board.h create mode 100644 bsp/raspberry-pi/raspi4-64/drivers/drv_dsi_touch.c rename bsp/raspberry-pi/raspi4-64/{driver => drivers}/drv_eth.c (57%) create mode 100644 bsp/raspberry-pi/raspi4-64/drivers/drv_eth.h create mode 100644 bsp/raspberry-pi/raspi4-64/drivers/drv_gpio.c rename bsp/raspberry-pi/raspi4-64/{driver => drivers}/drv_gpio.h (87%) create mode 100644 bsp/raspberry-pi/raspi4-64/drivers/drv_gtimer.c create mode 100644 bsp/raspberry-pi/raspi4-64/drivers/drv_hdmi.c create mode 100644 bsp/raspberry-pi/raspi4-64/drivers/drv_hdmi.h rename bsp/raspberry-pi/raspi4-64/{driver => drivers}/drv_sdio.c (75%) create mode 100644 bsp/raspberry-pi/raspi4-64/drivers/drv_sdio.h create mode 100644 bsp/raspberry-pi/raspi4-64/drivers/drv_spi.c create mode 100644 bsp/raspberry-pi/raspi4-64/drivers/drv_spi.h rename bsp/raspberry-pi/raspi4-64/{driver => drivers}/drv_uart.c (83%) rename bsp/raspberry-pi/raspi4-64/{driver => drivers}/drv_uart.h (61%) rename bsp/raspberry-pi/raspi4-64/{driver => drivers}/drv_wdt.c (65%) rename bsp/raspberry-pi/raspi4-64/{driver => drivers}/drv_wdt.h (86%) rename bsp/raspberry-pi/raspi4-64/{driver => drivers}/mbox.c (72%) create mode 100644 bsp/raspberry-pi/raspi4-64/drivers/mbox.h create mode 100644 bsp/raspberry-pi/raspi4-64/drivers/raspi4.h create mode 100644 bsp/raspberry-pi/raspi4-64/link_smart.lds create mode 100644 bsp/raspberry-pi/raspi4-64/tools/config.txt create mode 100644 bsp/raspberry-pi/raspi4-64/tools/u-boot64.bin diff --git a/bsp/raspberry-pi/raspi4-64/.config b/bsp/raspberry-pi/raspi4-64/.config index 840585ccaa..7228a42d85 100644 --- a/bsp/raspberry-pi/raspi4-64/.config +++ b/bsp/raspberry-pi/raspi4-64/.config @@ -9,32 +9,35 @@ CONFIG_RT_NAME_MAX=8 # CONFIG_RT_USING_ARCH_DATA_TYPE is not set # CONFIG_RT_USING_SMART is not set -# CONFIG_RT_USING_SMP is not set -CONFIG_RT_ALIGN_SIZE=8 +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_TICK_PER_SECOND=1000 CONFIG_RT_USING_OVERFLOW_CHECK=y CONFIG_RT_USING_HOOK=y CONFIG_RT_HOOK_USING_FUNC_PTR=y CONFIG_RT_USING_IDLE_HOOK=y CONFIG_RT_IDLE_HOOK_LIST_SIZE=4 -CONFIG_IDLE_THREAD_STACK_SIZE=4096 +CONFIG_IDLE_THREAD_STACK_SIZE=8192 +CONFIG_SYSTEM_THREAD_STACK_SIZE=8192 CONFIG_RT_USING_TIMER_SOFT=y CONFIG_RT_TIMER_THREAD_PRIO=4 -CONFIG_RT_TIMER_THREAD_STACK_SIZE=4096 +CONFIG_RT_TIMER_THREAD_STACK_SIZE=8192 # # kservice optimization # -# CONFIG_RT_KSERVICE_USING_STDLIB is not set +CONFIG_RT_KSERVICE_USING_STDLIB=y +# CONFIG_RT_KSERVICE_USING_STDLIB_MEMORY is not set # CONFIG_RT_KSERVICE_USING_TINY_SIZE is not set # CONFIG_RT_USING_TINY_FFS is not set CONFIG_RT_KPRINTF_USING_LONGLONG=y CONFIG_RT_DEBUG=y -# CONFIG_RT_DEBUG_COLOR is not set +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 @@ -60,13 +63,13 @@ CONFIG_RT_USING_MESSAGEQUEUE=y # Memory Management # CONFIG_RT_PAGE_MAX_ORDER=11 -CONFIG_RT_USING_MEMPOOL=y -CONFIG_RT_USING_SMALL_MEM=y -# CONFIG_RT_USING_SLAB is not set +# CONFIG_RT_USING_MEMPOOL is not set +# CONFIG_RT_USING_SMALL_MEM is not set +CONFIG_RT_USING_SLAB=y # CONFIG_RT_USING_MEMHEAP is not set -CONFIG_RT_USING_SMALL_MEM_AS_HEAP=y +# CONFIG_RT_USING_SMALL_MEM_AS_HEAP is not set # CONFIG_RT_USING_MEMHEAP_AS_HEAP is not set -# CONFIG_RT_USING_SLAB_AS_HEAP is not set +CONFIG_RT_USING_SLAB_AS_HEAP=y # CONFIG_RT_USING_USERHEAP is not set # CONFIG_RT_USING_NOHEAP is not set # CONFIG_RT_USING_MEMTRACE is not set @@ -79,13 +82,15 @@ CONFIG_RT_USING_HEAP=y CONFIG_RT_USING_DEVICE=y # CONFIG_RT_USING_DEVICE_OPS is not set # CONFIG_RT_USING_DM is not set -# CONFIG_RT_USING_INTERRUPT_INFO is not set +CONFIG_RT_USING_INTERRUPT_INFO=y CONFIG_RT_USING_CONSOLE=y -CONFIG_RT_CONSOLEBUF_SIZE=128 +CONFIG_RT_CONSOLEBUF_SIZE=256 CONFIG_RT_CONSOLE_DEVICE_NAME="uart0" CONFIG_RT_VER_NUM=0x50000 +# CONFIG_RT_USING_STDC_ATOMIC is not set CONFIG_ARCH_CPU_64BIT=y CONFIG_RT_USING_CACHE=y +CONFIG_RT_USING_HW_ATOMIC=y # CONFIG_ARCH_ARM_BOOTWITH_FLUSH_CACHE is not set # CONFIG_ARCH_CPU_STACK_GROWS_UPWARD is not set # CONFIG_RT_USING_CPU_FFS is not set @@ -99,7 +104,7 @@ CONFIG_ARCH_ARMV8=y # CONFIG_RT_USING_COMPONENTS_INIT=y CONFIG_RT_USING_USER_MAIN=y -CONFIG_RT_MAIN_THREAD_STACK_SIZE=4096 +CONFIG_RT_MAIN_THREAD_STACK_SIZE=8192 CONFIG_RT_MAIN_THREAD_PRIORITY=10 # CONFIG_RT_USING_LEGACY is not set CONFIG_RT_USING_MSH=y @@ -107,7 +112,7 @@ CONFIG_RT_USING_FINSH=y CONFIG_FINSH_USING_MSH=y CONFIG_FINSH_THREAD_NAME="tshell" CONFIG_FINSH_THREAD_PRIORITY=20 -CONFIG_FINSH_THREAD_STACK_SIZE=4096 +CONFIG_FINSH_THREAD_STACK_SIZE=8192 CONFIG_FINSH_USING_HISTORY=y CONFIG_FINSH_HISTORY_LINES=5 CONFIG_FINSH_USING_SYMTAB=y @@ -120,9 +125,9 @@ CONFIG_FINSH_ARG_MAX=10 CONFIG_RT_USING_DFS=y CONFIG_DFS_USING_POSIX=y CONFIG_DFS_USING_WORKDIR=y -CONFIG_DFS_FILESYSTEMS_MAX=2 -CONFIG_DFS_FILESYSTEM_TYPES_MAX=2 -CONFIG_DFS_FD_MAX=16 +CONFIG_DFS_FILESYSTEMS_MAX=4 +CONFIG_DFS_FILESYSTEM_TYPES_MAX=4 +CONFIG_DFS_FD_MAX=32 # CONFIG_RT_USING_DFS_MNTTABLE is not set CONFIG_RT_USING_DFS_ELMFAT=y @@ -151,7 +156,7 @@ CONFIG_RT_USING_DFS_DEVFS=y # CONFIG_RT_USING_DFS_ROMFS is not set # CONFIG_RT_USING_DFS_CROMFS is not set # CONFIG_RT_USING_DFS_RAMFS is not set -# CONFIG_RT_USING_DFS_TMPFS is not set +CONFIG_RT_USING_DFS_TMPFS=y # CONFIG_RT_USING_DFS_NFS is not set # CONFIG_RT_USING_FAL is not set @@ -169,41 +174,51 @@ CONFIG_RT_USING_SERIAL_V1=y CONFIG_RT_SERIAL_USING_DMA=y CONFIG_RT_SERIAL_RB_BUFSZ=64 # CONFIG_RT_USING_CAN is not set -# CONFIG_RT_USING_HWTIMER is not set +CONFIG_RT_USING_HWTIMER=y # CONFIG_RT_USING_CPUTIME is not set -# CONFIG_RT_USING_I2C is not set +CONFIG_RT_USING_I2C=y +# CONFIG_RT_I2C_DEBUG is not set +CONFIG_RT_USING_I2C_BITOPS=y +# CONFIG_RT_I2C_BITOPS_DEBUG is not set # CONFIG_RT_USING_PHY is not set CONFIG_RT_USING_PIN=y # CONFIG_RT_USING_ADC is not set # CONFIG_RT_USING_DAC is not set -# CONFIG_RT_USING_NULL is not set -# CONFIG_RT_USING_ZERO is not set -# CONFIG_RT_USING_RANDOM is not set +CONFIG_RT_USING_NULL=y +CONFIG_RT_USING_ZERO=y +CONFIG_RT_USING_RANDOM=y # 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_FDT is not set CONFIG_RT_USING_RTC=y -CONFIG_RT_USING_ALARM=y -# CONFIG_RT_USING_SOFT_RTC is not set +# CONFIG_RT_USING_ALARM is not set +CONFIG_RT_USING_SOFT_RTC=y CONFIG_RT_USING_SDIO=y -CONFIG_RT_SDIO_STACK_SIZE=512 +CONFIG_RT_SDIO_STACK_SIZE=8192 CONFIG_RT_SDIO_THREAD_PRIORITY=15 CONFIG_RT_MMCSD_STACK_SIZE=8192 CONFIG_RT_MMCSD_THREAD_PREORITY=22 CONFIG_RT_MMCSD_MAX_PARTITION=16 # CONFIG_RT_SDIO_DEBUG is not set -# CONFIG_RT_USING_SPI is not set +CONFIG_RT_USING_SPI=y +# CONFIG_RT_USING_SPI_BITOPS is not set +# 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_LCD is not set +CONFIG_RT_USING_TOUCH=y +# CONFIG_RT_TOUCH_PIN_IRQ is not set +CONFIG_RT_USING_LCD=y # CONFIG_RT_USING_HWCRYPTO is not set # CONFIG_RT_USING_PULSE_ENCODER is not set # CONFIG_RT_USING_INPUT_CAPTURE is not set -# CONFIG_RT_USING_DEV_BUS is not set +CONFIG_RT_USING_DEV_BUS=y # CONFIG_RT_USING_WIFI is not set # CONFIG_RT_USING_VIRTIO is not set @@ -222,10 +237,18 @@ CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8 # # POSIX (Portable Operating System Interface) layer # -# CONFIG_RT_USING_POSIX_FS is not set -# CONFIG_RT_USING_POSIX_DELAY is not set -# CONFIG_RT_USING_POSIX_CLOCK is not set -# CONFIG_RT_USING_POSIX_TIMER is not set +CONFIG_RT_USING_POSIX_FS=y +CONFIG_RT_USING_POSIX_DEVIO=y +CONFIG_RT_USING_POSIX_STDIO=y +# CONFIG_RT_USING_POSIX_POLL is not set +# CONFIG_RT_USING_POSIX_SELECT is not set +# CONFIG_RT_USING_POSIX_SOCKET is not set +CONFIG_RT_USING_POSIX_TERMIOS=y +# CONFIG_RT_USING_POSIX_AIO is not set +# CONFIG_RT_USING_POSIX_MMAN is not set +CONFIG_RT_USING_POSIX_DELAY=y +CONFIG_RT_USING_POSIX_CLOCK=y +CONFIG_RT_USING_POSIX_TIMER=y # CONFIG_RT_USING_PTHREADS is not set # CONFIG_RT_USING_MODULE is not set @@ -254,6 +277,7 @@ CONFIG_SAL_USING_LWIP=y # CONFIG_SAL_USING_AT is not set # CONFIG_SAL_USING_TLS is not set CONFIG_SAL_USING_POSIX=y +# CONFIG_SAL_USING_AF_UNIX is not set CONFIG_RT_USING_NETDEV=y CONFIG_NETDEV_USING_IFCONFIG=y CONFIG_NETDEV_USING_PING=y @@ -266,10 +290,10 @@ CONFIG_NETDEV_IPV6=0 CONFIG_RT_USING_LWIP=y # CONFIG_RT_USING_LWIP_LOCAL_VERSION is not set # CONFIG_RT_USING_LWIP141 is not set -CONFIG_RT_USING_LWIP203=y -# CONFIG_RT_USING_LWIP212 is not set +# CONFIG_RT_USING_LWIP203 is not set +CONFIG_RT_USING_LWIP212=y # CONFIG_RT_USING_LWIP_LATEST is not set -CONFIG_RT_USING_LWIP_VER_NUM=0x20003 +CONFIG_RT_USING_LWIP_VER_NUM=0x20102 # CONFIG_RT_USING_LWIP_IPV6 is not set CONFIG_RT_LWIP_MEM_ALIGNMENT=4 CONFIG_RT_LWIP_IGMP=y @@ -283,30 +307,30 @@ CONFIG_IP_SOF_BROADCAST_RECV=1 # # Static IPv4 Address # -CONFIG_RT_LWIP_IPADDR="192.168.1.30" -CONFIG_RT_LWIP_GWADDR="192.168.1.1" +CONFIG_RT_LWIP_IPADDR="192.168.137.100" +CONFIG_RT_LWIP_GWADDR="192.168.137.1" CONFIG_RT_LWIP_MSKADDR="255.255.255.0" CONFIG_RT_LWIP_UDP=y CONFIG_RT_LWIP_TCP=y CONFIG_RT_LWIP_RAW=y # CONFIG_RT_LWIP_PPP is not set -CONFIG_RT_MEMP_NUM_NETCONN=8 +CONFIG_RT_MEMP_NUM_NETCONN=16 CONFIG_RT_LWIP_PBUF_NUM=16 CONFIG_RT_LWIP_RAW_PCB_NUM=4 -CONFIG_RT_LWIP_UDP_PCB_NUM=4 -CONFIG_RT_LWIP_TCP_PCB_NUM=4 +CONFIG_RT_LWIP_UDP_PCB_NUM=8 +CONFIG_RT_LWIP_TCP_PCB_NUM=8 CONFIG_RT_LWIP_TCP_SEG_NUM=40 -CONFIG_RT_LWIP_TCP_SND_BUF=8196 -CONFIG_RT_LWIP_TCP_WND=8196 +CONFIG_RT_LWIP_TCP_SND_BUF=8192 +CONFIG_RT_LWIP_TCP_WND=8192 CONFIG_RT_LWIP_TCPTHREAD_PRIORITY=10 CONFIG_RT_LWIP_TCPTHREAD_MBOX_SIZE=8 -CONFIG_RT_LWIP_TCPTHREAD_STACKSIZE=4096 +CONFIG_RT_LWIP_TCPTHREAD_STACKSIZE=16384 # CONFIG_LWIP_NO_RX_THREAD is not set # CONFIG_LWIP_NO_TX_THREAD is not set CONFIG_RT_LWIP_ETHTHREAD_PRIORITY=12 -CONFIG_RT_LWIP_ETHTHREAD_STACKSIZE=4096 +CONFIG_RT_LWIP_ETHTHREAD_STACKSIZE=16384 CONFIG_RT_LWIP_ETHTHREAD_MBOX_SIZE=8 -# CONFIG_RT_LWIP_REASSEMBLY_FRAG is not set +CONFIG_RT_LWIP_REASSEMBLY_FRAG=y CONFIG_LWIP_NETIF_STATUS_CALLBACK=1 CONFIG_LWIP_NETIF_LINK_CALLBACK=1 CONFIG_SO_REUSE=1 @@ -314,8 +338,8 @@ CONFIG_LWIP_SO_RCVTIMEO=1 CONFIG_LWIP_SO_SNDTIMEO=1 CONFIG_LWIP_SO_RCVBUF=1 CONFIG_LWIP_SO_LINGER=0 -# CONFIG_RT_LWIP_NETIF_LOOPBACK is not set -CONFIG_LWIP_NETIF_LOOPBACK=0 +CONFIG_RT_LWIP_NETIF_LOOPBACK=y +CONFIG_LWIP_NETIF_LOOPBACK=1 # CONFIG_RT_LWIP_STATS is not set # CONFIG_RT_LWIP_USING_HW_CHECKSUM is not set CONFIG_RT_LWIP_USING_PING=y @@ -326,11 +350,11 @@ CONFIG_RT_LWIP_USING_PING=y # # Utilities # -CONFIG_RT_USING_RYM=y -# CONFIG_YMODEM_USING_CRC_TABLE is not set -CONFIG_YMODEM_USING_FILE_TRANSFER=y +# CONFIG_RT_USING_RYM is not set # CONFIG_RT_USING_ULOG is not set -# CONFIG_RT_USING_UTEST is not set +CONFIG_RT_USING_UTEST=y +CONFIG_UTEST_THR_STACK_SIZE=8192 +CONFIG_UTEST_THR_PRIORITY=20 # CONFIG_RT_USING_VAR_EXPORT is not set CONFIG_RT_USING_ADT=y # CONFIG_RT_USING_RT_LINK is not set @@ -427,8 +451,6 @@ CONFIG_RT_USING_ADT=y # CONFIG_PKG_USING_AGILE_FTP is not set # CONFIG_PKG_USING_EMBEDDEDPROTO is not set # CONFIG_PKG_USING_RT_LINK_HW is not set -# CONFIG_PKG_USING_RYANMQTT is not set -# CONFIG_PKG_USING_RYANW5500 is not set # CONFIG_PKG_USING_LORA_PKT_FWD is not set # CONFIG_PKG_USING_LORA_GW_DRIVER_LIB is not set # CONFIG_PKG_USING_LORA_PKT_SNIFFER is not set @@ -436,7 +458,6 @@ CONFIG_RT_USING_ADT=y # CONFIG_PKG_USING_SMALL_MODBUS is not set # CONFIG_PKG_USING_NET_SERVER is not set # CONFIG_PKG_USING_ZFTP is not set -# CONFIG_PKG_USING_WOL is not set # # security packages @@ -527,6 +548,7 @@ CONFIG_RT_USING_ADT=y # CONFIG_PKG_USING_SEGGER_RTT is not set # CONFIG_PKG_USING_RDB is not set # CONFIG_PKG_USING_ULOG_EASYFLASH is not set +# CONFIG_PKG_USING_ULOG_FILE is not set # CONFIG_PKG_USING_LOGMGR is not set # CONFIG_PKG_USING_ADBD is not set # CONFIG_PKG_USING_COREMARK is not set @@ -560,6 +582,7 @@ CONFIG_RT_USING_ADT=y # CONFIG_PKG_USING_CBOX is not set # CONFIG_PKG_USING_SNOWFLAKE is not set # CONFIG_PKG_USING_HASH_MATCH is not set +# CONFIG_PKG_USING_FIRE_PID_CURVE is not set # CONFIG_PKG_USING_ARMV7M_DWT_TOOL is not set # CONFIG_PKG_USING_VOFA_PLUS is not set @@ -632,93 +655,19 @@ CONFIG_RT_USING_ADT=y # CONFIG_PKG_USING_TFDB is not set # CONFIG_PKG_USING_QPC is not set # CONFIG_PKG_USING_AGILE_UPGRADE is not set -# CONFIG_PKG_USING_FLASH_BLOB is not set # # peripheral libraries and drivers # - -# -# sensors drivers -# -# CONFIG_PKG_USING_LSM6DSM is not set -# CONFIG_PKG_USING_LSM6DSL is not set -# CONFIG_PKG_USING_LPS22HB is not set -# CONFIG_PKG_USING_HTS221 is not set -# CONFIG_PKG_USING_LSM303AGR is not set -# CONFIG_PKG_USING_BME280 is not set -# CONFIG_PKG_USING_BME680 is not set -# CONFIG_PKG_USING_BMA400 is not set -# CONFIG_PKG_USING_BMI160_BMX160 is not set -# CONFIG_PKG_USING_SPL0601 is not set -# CONFIG_PKG_USING_MS5805 is not set -# CONFIG_PKG_USING_DA270 is not set -# CONFIG_PKG_USING_DF220 is not set -# CONFIG_PKG_USING_HSHCAL001 is not set -# CONFIG_PKG_USING_BH1750 is not set -# CONFIG_PKG_USING_MPU6XXX is not set -# CONFIG_PKG_USING_AHT10 is not set -# CONFIG_PKG_USING_AP3216C is not set -# CONFIG_PKG_USING_TSL4531 is not set -# CONFIG_PKG_USING_DS18B20 is not set -# CONFIG_PKG_USING_DHT11 is not set -# CONFIG_PKG_USING_DHTXX is not set -# CONFIG_PKG_USING_GY271 is not set -# CONFIG_PKG_USING_GP2Y10 is not set -# CONFIG_PKG_USING_SGP30 is not set -# CONFIG_PKG_USING_HDC1000 is not set -# CONFIG_PKG_USING_BMP180 is not set -# CONFIG_PKG_USING_BMP280 is not set -# CONFIG_PKG_USING_SHTC1 is not set -# CONFIG_PKG_USING_BMI088 is not set -# CONFIG_PKG_USING_HMC5883 is not set -# CONFIG_PKG_USING_MAX6675 is not set -# CONFIG_PKG_USING_TMP1075 is not set -# CONFIG_PKG_USING_SR04 is not set -# CONFIG_PKG_USING_CCS811 is not set -# CONFIG_PKG_USING_PMSXX is not set -# CONFIG_PKG_USING_RT3020 is not set -# CONFIG_PKG_USING_MLX90632 is not set -# CONFIG_PKG_USING_MLX90393 is not set -# CONFIG_PKG_USING_MLX90392 is not set -# CONFIG_PKG_USING_MLX90397 is not set -# CONFIG_PKG_USING_MS5611 is not set -# CONFIG_PKG_USING_MAX31865 is not set -# CONFIG_PKG_USING_VL53L0X is not set -# CONFIG_PKG_USING_INA260 is not set -# CONFIG_PKG_USING_MAX30102 is not set -# CONFIG_PKG_USING_INA226 is not set -# CONFIG_PKG_USING_LIS2DH12 is not set -# CONFIG_PKG_USING_HS300X is not set -# CONFIG_PKG_USING_ZMOD4410 is not set -# CONFIG_PKG_USING_ISL29035 is not set -# CONFIG_PKG_USING_MMC3680KJ is not set -# CONFIG_PKG_USING_QMP6989 is not set -# CONFIG_PKG_USING_BALANCE is not set +# CONFIG_PKG_USING_SENSORS_DRIVERS is not set +# CONFIG_PKG_USING_REALTEK_AMEBA is not set # CONFIG_PKG_USING_SHT2X is not set # CONFIG_PKG_USING_SHT3X is not set -# CONFIG_PKG_USING_AD7746 is not set # CONFIG_PKG_USING_ADT74XX is not set -# CONFIG_PKG_USING_MAX17048 is not set # CONFIG_PKG_USING_AS7341 is not set -# CONFIG_PKG_USING_CW2015 is not set -# CONFIG_PKG_USING_ICM20608 is not set -# CONFIG_PKG_USING_PAJ7620 is not set - -# -# touch drivers -# -# CONFIG_PKG_USING_GT9147 is not set -# CONFIG_PKG_USING_GT1151 is not set -# CONFIG_PKG_USING_GT917S is not set -# CONFIG_PKG_USING_GT911 is not set -# CONFIG_PKG_USING_FT6206 is not set -# CONFIG_PKG_USING_FT5426 is not set -# CONFIG_PKG_USING_FT6236 is not set -# CONFIG_PKG_USING_XPT2046_TOUCH is not set -# CONFIG_PKG_USING_REALTEK_AMEBA is not set # CONFIG_PKG_USING_STM32_SDIO is not set # CONFIG_PKG_USING_ESP_IDF is not set +# CONFIG_PKG_USING_ICM20608 is not set # CONFIG_PKG_USING_BUTTON is not set # CONFIG_PKG_USING_PCF8574 is not set # CONFIG_PKG_USING_SX12XX is not set @@ -741,9 +690,12 @@ CONFIG_RT_USING_ADT=y # CONFIG_PKG_USING_AGILE_LED is not set # CONFIG_PKG_USING_AT24CXX is not set # CONFIG_PKG_USING_MOTIONDRIVER2RTT is not set +# CONFIG_PKG_USING_AD7746 is not set # CONFIG_PKG_USING_PCA9685 is not set # CONFIG_PKG_USING_I2C_TOOLS is not set # CONFIG_PKG_USING_NRF24L01 is not set +# CONFIG_PKG_USING_TOUCH_DRIVERS is not set +# CONFIG_PKG_USING_MAX17048 is not set # CONFIG_PKG_USING_RPLIDAR is not set # CONFIG_PKG_USING_AS608 is not set # CONFIG_PKG_USING_RC522 is not set @@ -758,6 +710,7 @@ CONFIG_RT_USING_ADT=y # CONFIG_PKG_USING_CAN_YMODEM is not set # CONFIG_PKG_USING_LORA_RADIO_DRIVER is not set # CONFIG_PKG_USING_QLED is not set +# CONFIG_PKG_USING_PAJ7620 is not set # CONFIG_PKG_USING_AGILE_CONSOLE is not set # CONFIG_PKG_USING_LD3320 is not set # CONFIG_PKG_USING_WK2124 is not set @@ -788,11 +741,10 @@ CONFIG_RT_USING_ADT=y # CONFIG_PKG_USING_BL_MCU_SDK is not set # CONFIG_PKG_USING_SOFT_SERIAL is not set # CONFIG_PKG_USING_MB85RS16 is not set +# CONFIG_PKG_USING_CW2015 is not set # CONFIG_PKG_USING_RFM300 is not set # CONFIG_PKG_USING_IO_INPUT_FILTER is not set # CONFIG_PKG_USING_RASPBERRYPI_PICO_SDK is not set -# CONFIG_PKG_USING_LRF_NV7LIDAR is not set -# CONFIG_PKG_USING_FINGERPRINT is not set # # AI packages @@ -807,12 +759,6 @@ CONFIG_RT_USING_ADT=y # CONFIG_PKG_USING_QUEST is not set # CONFIG_PKG_USING_NAXOS is not set -# -# Signal Processing and Control Algorithm Packages -# -# CONFIG_PKG_USING_FIRE_PID_CURVE is not set -# CONFIG_PKG_USING_UKAL is not set - # # miscellaneous packages # @@ -864,6 +810,7 @@ CONFIG_RT_USING_ADT=y # CONFIG_PKG_USING_VI is not set # CONFIG_PKG_USING_KI is not set # CONFIG_PKG_USING_ARMv7M_DWT is not set +# CONFIG_PKG_USING_UKAL is not set # CONFIG_PKG_USING_CRCLIB is not set # CONFIG_PKG_USING_LWGPS is not set # CONFIG_PKG_USING_STATE_MACHINE is not set @@ -874,7 +821,6 @@ CONFIG_RT_USING_ADT=y # CONFIG_PKG_USING_SLCAN2RTT is not set # CONFIG_PKG_USING_SOEM is not set # CONFIG_PKG_USING_QPARAM is not set -# CONFIG_PKG_USING_CorevMCU_CLI is not set # # Arduino libraries @@ -891,17 +837,16 @@ CONFIG_RT_USING_ADT=y # # Sensors # -# CONFIG_PKG_USING_ARDUINO_SENSOR_DEVICE_DRIVERS is not set -# CONFIG_PKG_USING_ARDUINO_CAPACITIVESENSOR is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_BMP280 is not set # CONFIG_PKG_USING_ARDUINO_ADAFRUIT_ADXL375 is not set # CONFIG_PKG_USING_ARDUINO_ADAFRUIT_VL53L0X is not set -# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_VL53L1X is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_LIS3DHTR is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_DHT is not set +# CONFIG_PKG_USING_ARDUINO_CAPACITIVESENSOR is not set # CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SENSOR is not set -# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_VL6180X is not set # CONFIG_PKG_USING_ADAFRUIT_MAX31855 is not set # CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MAX31865 is not set # CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MAX31856 is not set -# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MAX6675 is not set # CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MLX90614 is not set # CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LSM9DS1 is not set # CONFIG_PKG_USING_ARDUINO_ADAFRUIT_AHTX0 is not set @@ -982,7 +927,6 @@ CONFIG_RT_USING_ADT=y # CONFIG_PKG_USING_ARDUINO_ADAFRUIT_HTU21DF is not set # CONFIG_PKG_USING_ARDUINO_ADAFRUIT_AS7341 is not set # CONFIG_PKG_USING_ARDUINO_ADAFRUIT_HTU31D is not set -# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SENSORLAB is not set # CONFIG_PKG_USING_ARDUINO_ADAFRUIT_INA260 is not set # CONFIG_PKG_USING_ARDUINO_ADAFRUIT_TMP007_LIBRARY is not set # CONFIG_PKG_USING_ARDUINO_ADAFRUIT_L3GD20 is not set @@ -994,44 +938,11 @@ CONFIG_RT_USING_ADT=y # CONFIG_PKG_USING_ARDUINO_ADAFRUIT_VEML6070 is not set # CONFIG_PKG_USING_ARDUINO_ADAFRUIT_VEML6075 is not set # CONFIG_PKG_USING_ARDUINO_ADAFRUIT_VEML7700 is not set -# CONFIG_PKG_USING_ARDUINO_SEEED_LIS3DHTR is not set -# CONFIG_PKG_USING_ARDUINO_SEEED_DHT is not set -# CONFIG_PKG_USING_ARDUINO_SEEED_ADXL335 is not set -# CONFIG_PKG_USING_ARDUINO_SEEED_ADXL345 is not set -# CONFIG_PKG_USING_ARDUINO_SEEED_BME280 is not set -# CONFIG_PKG_USING_ARDUINO_SEEED_BMP280 is not set -# CONFIG_PKG_USING_ARDUINO_SEEED_H3LIS331DL is not set -# CONFIG_PKG_USING_ARDUINO_SEEED_MMA7660 is not set -# CONFIG_PKG_USING_ARDUINO_SEEED_TSL2561 is not set -# CONFIG_PKG_USING_ARDUINO_SEEED_PAJ7620 is not set -# CONFIG_PKG_USING_ARDUINO_SEEED_VL53L0X is not set -# CONFIG_PKG_USING_SEEED_ITG3200 is not set -# CONFIG_PKG_USING_ARDUINO_SEEED_SHT31 is not set -# CONFIG_PKG_USING_ARDUINO_SEEED_HP20X is not set -# CONFIG_PKG_USING_ARDUINO_SEEED_DRV2605L is not set -# CONFIG_PKG_USING_ARDUINO_SEEED_BBM150 is not set -# CONFIG_PKG_USING_ARDUINO_SEEED_HMC5883L is not set -# CONFIG_PKG_USING_ARDUINO_SEEED_LSM303DLH is not set -# CONFIG_PKG_USING_ARDUINO_SEEED_TCS3414CS is not set -# CONFIG_PKG_USING_SEEED_MP503 is not set -# CONFIG_PKG_USING_ARDUINO_SEEED_BMP085 is not set -# CONFIG_PKG_USING_ARDUINO_SEEED_HIGHTEMP is not set -# CONFIG_PKG_USING_ARDUINO_SEEED_VEML6070 is not set -# CONFIG_PKG_USING_ARDUINO_SEEED_SI1145 is not set -# CONFIG_PKG_USING_ARDUINO_SEEED_SHT35 is not set -# CONFIG_PKG_USING_ARDUINO_SEEED_AT42QT1070 is not set -# CONFIG_PKG_USING_ARDUINO_SEEED_LSM6DS3 is not set -# CONFIG_PKG_USING_ARDUINO_SEEED_HDC1000 is not set -# CONFIG_PKG_USING_ARDUINO_SEEED_HM3301 is not set -# CONFIG_PKG_USING_ARDUINO_SEEED_MCP9600 is not set -# CONFIG_PKG_USING_ARDUINO_SEEED_LTC2941 is not set -# CONFIG_PKG_USING_ARDUINO_SEEED_LDC1612 is not set # # Display # # CONFIG_PKG_USING_ARDUINO_U8G2 is not set -# CONFIG_PKG_USING_SEEED_TM1637 is not set # # Timing @@ -1059,7 +970,6 @@ CONFIG_RT_USING_ADT=y # # CONFIG_PKG_USING_ARDUINO_ADAFRUIT_PCF8574 is not set # CONFIG_PKG_USING_ARDUINO_ADAFRUIT_PCA9685 is not set -# CONFIG_PKG_USING_ARDUINO_SEEED_PCF85063TP is not set # # Other @@ -1080,68 +990,9 @@ CONFIG_RT_USING_ADT=y # # Uncategorized # - -# -# Privated Packages of RealThread -# -# CONFIG_PKG_USING_CODEC is not set -# CONFIG_PKG_USING_PLAYER is not set -# CONFIG_PKG_USING_MPLAYER is not set -# CONFIG_PKG_USING_PERSIMMON_SRC is not set -# CONFIG_PKG_USING_JS_PERSIMMON is not set -# CONFIG_PKG_USING_JERRYSCRIPT_WIN32 is not set - -# -# Network Utilities -# -# CONFIG_PKG_USING_MDNS is not set -# CONFIG_PKG_USING_UPNP is not set -# CONFIG_PKG_USING_WICED is not set -# CONFIG_PKG_USING_CLOUDSDK is not set -# CONFIG_PKG_USING_POWER_MANAGER is not set -# CONFIG_PKG_USING_RT_OTA is not set -# CONFIG_PKG_USING_RTINSIGHT is not set -# CONFIG_PKG_USING_SMARTCONFIG is not set -# CONFIG_PKG_USING_RTX is not set -# CONFIG_RT_USING_TESTCASE is not set -# CONFIG_PKG_USING_NGHTTP2 is not set -# CONFIG_PKG_USING_AVS is not set -# CONFIG_PKG_USING_ALI_LINKKIT is not set -# CONFIG_PKG_USING_STS is not set -# CONFIG_PKG_USING_DLMS is not set -# CONFIG_PKG_USING_AUDIO_FRAMEWORK is not set -# CONFIG_PKG_USING_ZBAR is not set -# CONFIG_PKG_USING_MCF is not set -# CONFIG_PKG_USING_URPC is not set -# CONFIG_PKG_USING_DCM is not set -# CONFIG_PKG_USING_EMQ is not set -# CONFIG_PKG_USING_CFGM is not set -# CONFIG_PKG_USING_RT_CMSIS_DAP is not set -# CONFIG_PKG_USING_SMODULE is not set -# CONFIG_PKG_USING_SNFD is not set -# CONFIG_PKG_USING_UDBD is not set -# CONFIG_PKG_USING_BENCHMARK is not set -# CONFIG_PKG_USING_UBJSON is not set -# CONFIG_PKG_USING_DATATYPE is not set -# CONFIG_PKG_USING_FASTFS is not set -# CONFIG_PKG_USING_RIL is not set -# CONFIG_PKG_USING_WATCH_DCM_SVC is not set -# CONFIG_PKG_USING_WATCH_APP_FWK is not set -# CONFIG_PKG_USING_GUI_TEST is not set -# CONFIG_PKG_USING_PMEM is not set -# CONFIG_PKG_USING_LWRDP is not set -# CONFIG_PKG_USING_MASAN is not set -# CONFIG_PKG_USING_BSDIFF_LIB is not set -# CONFIG_PKG_USING_PRC_DIFF is not set - -# -# RT-Thread Smart -# -# CONFIG_PKG_USING_UKERNEL is not set -# CONFIG_PKG_USING_TRACE_AGENT is not set -# CONFIG_PKG_USING_DLOG is not set -# CONFIG_PKG_USING_EXT4 is not set CONFIG_BCM2711_SOC=y +CONFIG_BSP_SUPPORT_FPU=y +# CONFIG_BSP_USING_VM_MODE is not set # # Hardware Drivers Config @@ -1153,22 +1004,24 @@ CONFIG_BCM2711_SOC=y CONFIG_BSP_USING_UART=y CONFIG_RT_USING_UART0=y # CONFIG_RT_USING_UART1 is not set -# CONFIG_RT_USING_UART3 is not set -# CONFIG_RT_USING_UART4 is not set +CONFIG_RT_USING_UART3=y +CONFIG_RT_USING_UART4=y # CONFIG_RT_USING_UART5 is not set CONFIG_BSP_USING_GIC=y CONFIG_BSP_USING_GICV2=y +# CONFIG_BSP_USING_GICV3 is not set CONFIG_BSP_USING_PIN=y +# CONFIG_BSP_USING_SPI is not set CONFIG_BSP_USING_CORETIMER=y # CONFIG_BSP_USING_SYSTIMER is not set -# CONFIG_BSP_USING_ETH is not set CONFIG_BSP_USING_WDT=y -CONFIG_BSP_USING_RTC=y -CONFIG_BSP_USING_ALARM=y +# CONFIG_BSP_USING_RTC is not set CONFIG_BSP_USING_SDIO=y CONFIG_BSP_USING_SDIO0=y # # Board Peripheral Drivers # -# CONFIG_BSP_USING_HDMI is not set +CONFIG_BSP_USING_HDMI=y +# CONFIG_BSP_USING_HDMI_DISPLAY is not set +# CONFIG_BSP_USING_TOUCH is not set diff --git a/bsp/raspberry-pi/raspi4-64/Kconfig b/bsp/raspberry-pi/raspi4-64/Kconfig index 2c0d51d4d4..fa7f8d3ba8 100644 --- a/bsp/raspberry-pi/raspi4-64/Kconfig +++ b/bsp/raspberry-pi/raspi4-64/Kconfig @@ -21,10 +21,11 @@ source "$PKGS_DIR/Kconfig" config BCM2711_SOC bool select ARCH_ARMV8 + select ARCH_ARM_MMU select RT_USING_CACHE select RT_USING_COMPONENTS_INIT select RT_USING_USER_MAIN select ARCH_CPU_64BIT default y -source "driver/Kconfig" +source "drivers/Kconfig" diff --git a/bsp/raspberry-pi/raspi4-64/README.md b/bsp/raspberry-pi/raspi4-64/README.md index 7e969d6488..d7736efa47 100644 --- a/bsp/raspberry-pi/raspi4-64/README.md +++ b/bsp/raspberry-pi/raspi4-64/README.md @@ -11,61 +11,16 @@ ## 2. 编译说明 - - -### 2.1 Window上的环境搭建 - -Windows环境下推荐使用[env工具](https://www.rt-thread.org/page/download.html)进行编译。 - -首先下载windows上的aarch64的gcc交叉编译工具,版本为gcc-arm-8.3选择aarch64-elf就可以。 - -将推荐将gcc解压到`\env\tools\gnu_gcc\arm_gcc`目录下。 - -接着修改`bsp\raspberry-pi\raspi4-64\rtconfig.py` - -修改路径: +推荐使用[env工具](https://www.rt-thread.org/page/download.html),可以在console下进入到`bsp\raspberry-pi\raspi4-64`目录中,运行以下命令: ``` -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' +scons ``` -然后在`bsp\raspberry-pi\raspi4-64\`下输入scons编译即可。 +来编译这个板级支持包。如果编译正确无误,会产生 `rtthread.elf`, `rtthread.bin` 文件。 -**window环境搭建注意** - -下载完成`gcc-arm-8.3-2019.03-i686-mingw32-aarch64-elf.tar.xz`交叉编译工具链后,最好采用7-zip解压工具进行两次解压。 -确保解压目录下的`/bin/aarch64-elf-ld.exe`文件的size不为0。 -否则编译会出现如下错误: - -``` -collect2.exe:fatal error:CreateProcess:No such file or directory -``` - -### 2.2 Linux上的环境搭建 - -Linux下推荐使用[gcc工具][2]。Linux版本下gcc版本可采用`gcc-arm-8.3-2019.03-x86_64-aarch64-elf`。 - -将工具链解压到指定目录,并修改当前bsp下的`EXEC_PATH`为自定义gcc目录。 - -``` -PLATFORM = 'gcc' -EXEC_PATH = r'/opt/gcc-arm-8.3-2019.03-x86_64-aarch64-elf/bin/' -``` - -直接进入`bsp\raspberry-pi\raspi4-64`,输入scons编译即可。 - - -## 3. 执行 - -### 3.1 下载**Raspberry Pi Imager**,生成可以运行的raspbian SD卡 - -首先下载镜像 - -* [Raspberry Pi Imager for Ubuntu](https://downloads.raspberrypi.org/imager/imager_amd64.deb) -* [Raspberry Pi Imager for Windows](https://downloads.raspberrypi.org/imager/imager.exe) -* [Raspberry Pi Imager for macOS](https://downloads.raspberrypi.org/imager/imager.dmg) - -### 3.2 准备好串口线 +## 3. 环境搭建 +### 3.1 准备好串口线 目前版本是使用raspi4的 GPIO 14, GPIO 15来作路口输出,连线情况如下图所示: @@ -73,27 +28,61 @@ EXEC_PATH = r'/opt/gcc-arm-8.3-2019.03-x86_64-aarch64-elf/bin/' 串口参数: 115200 8N1 ,硬件和软件流控为关。 -### 3.3 程序下载 +### 3.2 RTT固件放在SD卡运行 -当编译生成了rtthread.bin文件后,我们可以将该文件放到sd卡上,并修改sd卡中的`config.txt`文件如下: +暂时不支持,需要使用 u-boot 加载。 + +### 3.3 RTT程序用uboot加载 + +此 bsp 的 `tools` 下可以找到 [u-boot64.bin](./tools/u-boot64.bin) 和 [config.txt](./tools/config.txt) 两个文件。将其与准备好的 sd 卡中文件替换即可。sd 卡推荐通过树莓派 [imager](https://www.raspberrypi.com/software/) 制作。 + +需要注意的以下步骤: + +**1.电脑上启动tftp服务器** + +windows系统电脑上可以安装tftpd搭建tftp服务器。将目录指定到`bsp\raspberry-pi\raspi4-64`。 + +**2.修改设置uboot** + +在控制台输入下列命令: ``` -enable_uart=1 -arm_64bit=1 -kernel=rtthread.bin -core_freq=250 +setenv bootcmd "dhcp 0x00208000 x.x.x.x:rtthread.bin;dcache flush;go 0x00208000" +saveenv +reset ``` -按上面的方法做好SD卡后,插入树莓派4,通电可以在串口上看到如下所示的输出信息: +其中`x.x.x.x`为tftp服务器的pc的ip地址。 -```text -heap: 0x000c9350 - 0x040c9350 +**3.修改链接脚本** +链接脚本会在 python 脚本中自行替换,不用处理 + +**3.插入网线** + +上述准备完成后,将网线插入,保证开发板和tftp服务器在同一个网段的路由器上。上电后uboot可以自动从tftp服务器上获取固件,然后开始执行了。 + +完成后可以看到串口的输出信息 + +``` \ | / - RT - Thread Operating System - / | \ 4.0.3 build Apr 16 2020 - 2006 - 2020 Copyright by rt-thread team -Hi, this is RT-Thread!! + / | \ 5.0.0 build Mar 29 2023 10:56:23 + 2006 - 2022 Copyright by RT-Thread team +lwIP-2.1.2 initialized! +EMMC: assuming clock rate to be 100MHz +[I/sal.skt] Socket Abstraction Layer initialize success. +[I/utest] utest is initialize success. +[I/utest] total utest testcase num: (0) +[I/DBG] version is B1 + +[I/SDIO] SD card capacity 31166976 KB. +found part[0], begin: 4194304, size: 256.0MB +found part[1], begin: 272629760, size: 3.856GB +file system initialization done! +cpu 2 boot success +cpu 1 boot success +cpu 3 boot success msh /> ``` @@ -103,11 +92,18 @@ msh /> | ------ | ---- | :------: | | UART | 支持 | UART0,UART2,UART3,UART4,UART5 | | GPIO | 支持 | - | +| SPI | 支持 | SPI0 | | MAILBOX | 支持 | - | +| WATCHDOG | 支持 | - | +| HDMI | 支持 | - | | SDIO | 支持 | - | | ETH | 支持 | - | -## 5. 联系人信息 +## 5. 注意事项 + +目前rt-thread程序可以使用的内存在100MB以内,可以通过调整`board.c`中`platform_mem_desc`表的数据进行相关内存的映射以及修改`board.h`来确定程序使用的堆栈大小。 + +## 6. 联系人信息 维护人:[bernard][5] diff --git a/bsp/raspberry-pi/raspi4-64/SConstruct b/bsp/raspberry-pi/raspi4-64/SConstruct index 33f65e4109..9bbc8af56e 100644 --- a/bsp/raspberry-pi/raspi4-64/SConstruct +++ b/bsp/raspberry-pi/raspi4-64/SConstruct @@ -11,20 +11,24 @@ TARGET = 'rtthread.' + rtconfig.TARGET_EXT DefaultEnvironment(tools=[]) env = Environment(tools = ['mingw'], - AS = rtconfig.AS, ASFLAGS = rtconfig.AFLAGS, - CC = rtconfig.CC, CFLAGS = rtconfig.CFLAGS, - CXX = rtconfig.CXX, CXXFLAGS = rtconfig.CXXFLAGS, - AR = rtconfig.AR, ARFLAGS = '-rc', + AS = rtconfig.AS, ASFLAGS = rtconfig.AFLAGS, + CC = rtconfig.CC, CFLAGS = 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'] +env['LINKCOM'] = '$LINK -o $TARGET $LINKFLAGS $__RPATH $SOURCES $_LIBDIRFLAGS -Wl,--start-group $_LIBFLAGS -Wl,--end-group' Export('RTT_ROOT') Export('rtconfig') # prepare building environment -objs = PrepareBuilding(env, RTT_ROOT, has_libcpu = False) +objs = PrepareBuilding(env, RTT_ROOT) + +if GetDepend('RT_USING_SMART'): + # use smart link.lds + env['LINKFLAGS'] = env['LINKFLAGS'].replace('link.lds', 'link_smart.lds') # make a building DoBuilding(TARGET, objs) - diff --git a/bsp/raspberry-pi/raspi4-64/applications/SConscript b/bsp/raspberry-pi/raspi4-64/applications/SConscript index 9bb9abae89..bda7b8b585 100644 --- a/bsp/raspberry-pi/raspi4-64/applications/SConscript +++ b/bsp/raspberry-pi/raspi4-64/applications/SConscript @@ -1,9 +1,8 @@ from building import * -import os -cwd = GetCurrentDir() -src = Glob('*.c') -CPPPATH = [cwd] +cwd = GetCurrentDir() +src = Glob('*.c') + Glob('*.cpp') +CPPPATH = [cwd, str(Dir('#'))] group = DefineGroup('Applications', src, depend = [''], CPPPATH = CPPPATH) diff --git a/bsp/raspberry-pi/raspi4-64/driver/SConscript b/bsp/raspberry-pi/raspi4-64/driver/SConscript deleted file mode 100644 index 533df8ac31..0000000000 --- a/bsp/raspberry-pi/raspi4-64/driver/SConscript +++ /dev/null @@ -1,9 +0,0 @@ -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/raspi4-64/driver/board.c b/bsp/raspberry-pi/raspi4-64/driver/board.c deleted file mode 100644 index c8c4a5617d..0000000000 --- a/bsp/raspberry-pi/raspi4-64/driver/board.c +++ /dev/null @@ -1,172 +0,0 @@ -/* - * Copyright (c) 2006-2021, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2020-04-16 bigmagic first version - * 2021-12-28 GuEe-GUI add smp support - */ - -#include -#include - -#include "board.h" -#include "drv_uart.h" - -#include "mmu.h" -#include "gic.h" -#include "gtimer.h" -#include "cpuport.h" -#include "interrupt.h" -#include "mbox.h" - -struct mem_desc platform_mem_desc[] = -{ - {0, 0x6400000, 0, NORMAL_MEM}, - {0xFE200000, 0xFE400000, 0xFE200000, DEVICE_MEM}, /* uart gpio */ - {0xFF800000, 0xFFA00000, 0xFF800000, DEVICE_MEM}, /* gic timer */ - {WDT_BASE, WDT_BASE + 0x1000, WDT_BASE, DEVICE_MEM}, /* wdt */ - {MBOX_ADDR, MBOX_ADDR + 0x200000, MBOX_ADDR, DEVICE_MEM}, /* mbox msg */ - {STIMER_BASE, STIMER_BASE + 0x200000, STIMER_BASE, DEVICE_MEM}, /* stimer */ - {MAC_BASE_ADDR, MAC_BASE_ADDR + 0x80000, MAC_BASE_ADDR, DEVICE_MEM}, /* mac */ - {MMC2_BASE_ADDR, MMC2_BASE_ADDR + 0x200000, MMC2_BASE_ADDR, DEVICE_MEM}, /* mmc */ - {ARM_TIMER_BASE, ARM_TIMER_BASE + 0x200000, ARM_TIMER_BASE, DEVICE_MEM}, /* arm timer */ - {SEND_DATA_NO_CACHE, SEND_DATA_NO_CACHE + 0x200000, SEND_DATA_NO_CACHE, NORMAL_MEM}, /* eth send */ - {RECV_DATA_NO_CACHE, RECV_DATA_NO_CACHE + 0x200000, RECV_DATA_NO_CACHE, NORMAL_MEM}, /* eth recv */ -}; - -const rt_uint32_t platform_mem_desc_size = sizeof(platform_mem_desc)/sizeof(platform_mem_desc[0]); - -#if !defined(BSP_USING_CORETIMER) && !defined(RT_USING_SMP) -void rt_hw_timer_isr(int vector, void *parameter) -{ - ARM_TIMER_IRQCLR = 0; - rt_tick_increase(); -} -#endif - -void rt_hw_timer_init(void) -{ -#if defined(BSP_USING_CORETIMER) || defined(RT_USING_SMP) - rt_hw_gtimer_init(); - core_timer_enable(0); -#else - rt_uint32_t apb_clock = 0; - rt_uint32_t timer_clock = 1000000; - - apb_clock = bcm271x_mbox_clock_get_rate(CORE_CLK_ID); - ARM_TIMER_PREDIV = (apb_clock/timer_clock - 1); - - ARM_TIMER_RELOAD = 0; - ARM_TIMER_LOAD = 0; - ARM_TIMER_IRQCLR = 1; - ARM_TIMER_CTRL = 0; - - ARM_TIMER_RELOAD = 1000000 / RT_TICK_PER_SECOND; - ARM_TIMER_LOAD = 1000000 / RT_TICK_PER_SECOND; - - /* 23-bit counter, enable interrupt, enable timer */ - ARM_TIMER_CTRL = (1 << 1) | (1 << 5) | (1 << 7); - - rt_hw_interrupt_install(ARM_TIMER_IRQ, rt_hw_timer_isr, RT_NULL, "tick"); - rt_hw_interrupt_umask(ARM_TIMER_IRQ); -#endif -} - -void idle_wfi(void) -{ - asm volatile ("wfi"); -} - -/** - * Initialize the Hardware related stuffs. Called from rtthread_startup() - * after interrupt disabled. - */ -void rt_hw_board_init(void) -{ - extern void *MMUTable; - rt_hw_mmu_map_init(&rt_kernel_space, (void*)0x80000000, 0x10000000, MMUTable, 0); - rt_hw_mmu_setup(&rt_kernel_space, platform_mem_desc, platform_mem_desc_size); - - /* initialize hardware interrupt */ - rt_hw_interrupt_init(); // in libcpu/interrupt.c. Set some data structures, no operation on device - - /* initialize uart */ - rt_hw_uart_init(); // driver/drv_uart.c -#if defined(RT_USING_CONSOLE) && defined(RT_USING_DEVICE) - /* set console device */ - rt_console_set_device(RT_CONSOLE_DEVICE_NAME); -#endif - -#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 - /* initialize timer for os tick */ - rt_hw_timer_init(); - rt_thread_idle_sethook(idle_wfi); - -#ifdef RT_USING_COMPONENTS_INIT - rt_components_board_init(); -#endif - -#ifdef RT_USING_SMP - /* install IPI handle */ - rt_hw_ipi_handler_install(IRQ_ARM_IPI_KICK, rt_scheduler_ipi_handler); - arm_gic_umask(0, IRQ_ARM_IPI_KICK); -#endif -} - -#ifdef RT_USING_SMP -static unsigned long cpu_release_paddr[] = -{ - [0] = 0xd8, - [1] = 0xe0, - [2] = 0xe8, - [3] = 0xf0, - [4] = 0 -}; - -void rt_hw_secondary_cpu_up(void) -{ - int i; - extern void secondary_cpu_start(void); - - for (i = 1; i < RT_CPUS_NR && cpu_release_paddr[i]; ++i) - { - __asm__ volatile ("str %0, [%1]"::"rZ"((unsigned long)secondary_cpu_start), "r"(cpu_release_paddr[i])); - rt_hw_dcache_flush_range(cpu_release_paddr[i], sizeof(cpu_release_paddr[i])); - __DSB(); - __SEV(); - } -} - -void secondary_cpu_c_start(void) -{ - int id; - - rt_hw_mmu_init(); - - id = rt_hw_cpu_id(); - rt_hw_spin_lock(&_cpus_lock); - - arm_gic_cpu_init(0, platform_get_gic_cpu_base()); - rt_hw_vector_init(); - rt_hw_gtimer_local_enable(); - core_timer_enable(id); - arm_gic_umask(0, IRQ_ARM_IPI_KICK); - - rt_kprintf("\rcall cpu %d on success\n", id); - - rt_system_scheduler_start(); -} - -void rt_hw_secondary_cpu_idle_exec(void) -{ - __WFE(); -} -#endif - diff --git a/bsp/raspberry-pi/raspi4-64/driver/board.h b/bsp/raspberry-pi/raspi4-64/driver/board.h deleted file mode 100644 index 1c65a92305..0000000000 --- a/bsp/raspberry-pi/raspi4-64/driver/board.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (c) 2006-2021, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2020-04-16 bigmagic first version - */ - -#ifndef BOARD_H__ -#define BOARD_H__ - -#include -#include "raspi4.h" - -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 + 64 * 1024 * 1024) - -#ifndef RT_USING_SMART -#define PV_OFFSET 0 -#define KERNEL_VADDR_START 0 -#endif - -void rt_hw_board_init(void); - -#endif diff --git a/bsp/raspberry-pi/raspi4-64/driver/drv_eth.h b/bsp/raspberry-pi/raspi4-64/driver/drv_eth.h deleted file mode 100644 index e2cce207e5..0000000000 --- a/bsp/raspberry-pi/raspi4-64/driver/drv_eth.h +++ /dev/null @@ -1,216 +0,0 @@ -/* - * Copyright (c) 2006-2021, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2020-10-30 bigmagic first version - */ - -#ifndef __DRV_ETH_H__ -#define __DRV_ETH_H__ - -#define MAC_REG (void *)(0xfd580000) - -#define SYS_REV_CTRL (0x00) -#define SYS_PORT_CTRL (0x04) -#define PORT_MODE_EXT_GPHY (3) - -#define GENET_SYS_OFF (0x0000) -#define SYS_RBUF_FLUSH_CTRL (GENET_SYS_OFF + 0x08) -#define SYS_TBUF_FLUSH_CTRL (GENET_SYS_OFF + 0x0c) - -#define GENET_EXT_OFF (0x0080) -#define EXT_RGMII_OOB_CTRL (GENET_EXT_OFF + 0x0c) -#define RGMII_LINK BIT(4) -#define OOB_DISABLE BIT(5) -#define RGMII_MODE_EN BIT(6) -#define ID_MODE_DIS BIT(16) - -#define GENET_RBUF_OFF (0x0300) -#define RBUF_TBUF_SIZE_CTRL (GENET_RBUF_OFF + 0xb4) -#define RBUF_CTRL (GENET_RBUF_OFF + 0x00) -#define RBUF_ALIGN_2B BIT(1) - -#define GENET_UMAC_OFF (0x0800) -#define UMAC_MIB_CTRL (GENET_UMAC_OFF + 0x580) -#define UMAC_MAX_FRAME_LEN (GENET_UMAC_OFF + 0x014) -#define UMAC_MAC0 (GENET_UMAC_OFF + 0x00c) -#define UMAC_MAC1 (GENET_UMAC_OFF + 0x010) -#define UMAC_CMD (GENET_UMAC_OFF + 0x008) -#define MDIO_CMD (GENET_UMAC_OFF + 0x614) -#define UMAC_TX_FLUSH (GENET_UMAC_OFF + 0x334) -#define MDIO_START_BUSY BIT(29) -#define MDIO_READ_FAIL BIT(28) -#define MDIO_RD (2 << 26) -#define MDIO_WR BIT(26) -#define MDIO_PMD_SHIFT (21) -#define MDIO_PMD_MASK (0x1f) -#define MDIO_REG_SHIFT (16) -#define MDIO_REG_MASK (0x1f) - -#define GENET_INTRL2_OFF (0x0200) -#define GENET_INTRL2_CPU_STAT (GENET_INTRL2_OFF + 0x00) -#define GENET_INTRL2_CPU_CLEAR (GENET_INTRL2_OFF + 0x08) -#define GENET_INTRL2_CPU_STAT_MASK (GENET_INTRL2_OFF + 0x0c) -#define GENET_INTRL2_CPU_SET_MASK (GENET_INTRL2_OFF + 0x10) -#define GENET_INTRL2_CPU_CLEAR_MASK (GENET_INTRL2_OFF + 0x14) -#define GENET_IRQ_MDIO_ERROR BIT(24) -#define GENET_IRQ_MDIO_DONE BIT(23) -#define GENET_IRQ_TXDMA_DONE BIT(16) -#define GENET_IRQ_RXDMA_DONE BIT(13) - -#define CMD_TX_EN BIT(0) -#define CMD_RX_EN BIT(1) -#define UMAC_SPEED_10 (0) -#define UMAC_SPEED_100 (1) -#define UMAC_SPEED_1000 (2) -#define UMAC_SPEED_2500 (3) -#define CMD_SPEED_SHIFT (2) -#define CMD_SPEED_MASK (3) -#define CMD_SW_RESET BIT(13) -#define CMD_LCL_LOOP_EN BIT(15) -#define CMD_TX_EN BIT(0) -#define CMD_RX_EN BIT(1) - -#define MIB_RESET_RX BIT(0) -#define MIB_RESET_RUNT BIT(1) -#define MIB_RESET_TX BIT(2) - -/* total number of Buffer Descriptors, same for Rx/Tx */ -#define TOTAL_DESCS (256) -#define RX_DESCS TOTAL_DESCS -#define TX_DESCS TOTAL_DESCS - -#define DEFAULT_Q (0x10) - -#define ETH_DATA_LEN (1500) -#define ETH_HLEN (14) -#define VLAN_HLEN (4) -#define ETH_FCS_LEN (4) -/* - * Body(1500) + EH_SIZE(14) + VLANTAG(4) + BRCMTAG(6) + FCS(4) = 1528. - * 1536 is multiple of 256 bytes - */ -#define ENET_BRCM_TAG_LEN (6) -#define ENET_PAD (8) -#define ENET_MAX_MTU_SIZE (ETH_DATA_LEN + ETH_HLEN + VLAN_HLEN + ENET_BRCM_TAG_LEN + ETH_FCS_LEN + ENET_PAD) - -/* Tx/Rx Dma Descriptor common bits */ -#define DMA_EN BIT(0) -#define DMA_RING_BUF_EN_SHIFT (0x01) -#define DMA_RING_BUF_EN_MASK (0xffff) -#define DMA_BUFLENGTH_MASK (0x0fff) -#define DMA_BUFLENGTH_SHIFT (16) -#define DMA_RING_SIZE_SHIFT (16) -#define DMA_OWN (0x8000) -#define DMA_EOP (0x4000) -#define DMA_SOP (0x2000) -#define DMA_WRAP (0x1000) -#define DMA_MAX_BURST_LENGTH (0x8) -/* Tx specific DMA descriptor bits */ -#define DMA_TX_UNDERRUN (0x0200) -#define DMA_TX_APPEND_CRC (0x0040) -#define DMA_TX_OW_CRC (0x0020) -#define DMA_TX_DO_CSUM (0x0010) -#define DMA_TX_QTAG_SHIFT (7) - -/* DMA rings size */ -#define DMA_RING_SIZE (0x40) -#define DMA_RINGS_SIZE (DMA_RING_SIZE * (DEFAULT_Q + 1)) - -/* DMA descriptor */ -#define DMA_DESC_LENGTH_STATUS (0x00) -#define DMA_DESC_ADDRESS_LO (0x04) -#define DMA_DESC_ADDRESS_HI (0x08) -#define DMA_DESC_SIZE (12) - -#define GENET_RX_OFF (0x2000) -#define GENET_RDMA_REG_OFF (GENET_RX_OFF + TOTAL_DESCS * DMA_DESC_SIZE) -#define GENET_TX_OFF (0x4000) -#define GENET_TDMA_REG_OFF (GENET_TX_OFF + TOTAL_DESCS * DMA_DESC_SIZE) - -#define DMA_FC_THRESH_HI (RX_DESCS >> 4) -#define DMA_FC_THRESH_LO (5) -#define DMA_FC_THRESH_VALUE ((DMA_FC_THRESH_LO << 16) | DMA_FC_THRESH_HI) - -#define DMA_XOFF_THRESHOLD_SHIFT (16) - -#define TDMA_RING_REG_BASE (GENET_TDMA_REG_OFF + DEFAULT_Q * DMA_RING_SIZE) -#define TDMA_READ_PTR (TDMA_RING_REG_BASE + 0x00) -#define TDMA_CONS_INDEX (TDMA_RING_REG_BASE + 0x08) -#define TDMA_PROD_INDEX (TDMA_RING_REG_BASE + 0x0c) -#define DMA_RING_BUF_SIZE (0x10) -#define DMA_START_ADDR (0x14) -#define DMA_END_ADDR (0x1c) -#define DMA_MBUF_DONE_THRESH (0x24) -#define TDMA_FLOW_PERIOD (TDMA_RING_REG_BASE + 0x28) -#define TDMA_WRITE_PTR (TDMA_RING_REG_BASE + 0x2c) - -#define RDMA_RING_REG_BASE (GENET_RDMA_REG_OFF + DEFAULT_Q * DMA_RING_SIZE) -#define RDMA_WRITE_PTR (RDMA_RING_REG_BASE + 0x00) -#define RDMA_PROD_INDEX (RDMA_RING_REG_BASE + 0x08) -#define RDMA_CONS_INDEX (RDMA_RING_REG_BASE + 0x0c) -#define RDMA_XON_XOFF_THRESH (RDMA_RING_REG_BASE + 0x28) -#define RDMA_READ_PTR (RDMA_RING_REG_BASE + 0x2c) - -#define TDMA_REG_BASE (GENET_TDMA_REG_OFF + DMA_RINGS_SIZE) -#define RDMA_REG_BASE (GENET_RDMA_REG_OFF + DMA_RINGS_SIZE) -#define DMA_RING_CFG (0x00) -#define DMA_CTRL (0x04) -#define DMA_SCB_BURST_SIZE (0x0c) - -#define RX_BUF_LENGTH (2048) -#define RX_TOTAL_BUFSIZE (RX_BUF_LENGTH * RX_DESCS) -#define RX_BUF_OFFSET (2) - -#define PHY_INTERFACE_MODE_RGMII (7) -#define PHY_INTERFACE_MODE_RGMII_RXID (9) - -#define BCM54213PE_MII_CONTROL (0x00) -#define BCM54213PE_MII_STATUS (0x01) -#define BCM54213PE_PHY_IDENTIFIER_HIGH (0x02) -#define BCM54213PE_PHY_IDENTIFIER_LOW (0x03) - -#define BCM54213PE_AUTO_NEGOTIATION_ADV (0x04) -#define BCM54213PE_AUTO_NEGOTIATION_LINK (0x05) -#define BCM54213PE_AUTO_NEGOTIATION_EXPANSION (0x06) - -#define BCM54213PE_NEXT_PAGE_TX (0x07) - -#define BCM54213PE_PARTNER_RX (0x08) - -#define BCM54213PE_CONTROL (0x09) -#define BCM54213PE_STATUS (0x0A) - -#define BCM54213PE_IEEE_EXTENDED_STATUS (0x0F) -#define BCM54213PE_PHY_EXTENDED_CONTROL (0x10) -#define BCM54213PE_PHY_EXTENDED_STATUS (0x11) - -#define BCM54213PE_RECEIVE_ERROR_COUNTER (0x12) -#define BCM54213PE_FALSE_C_S_COUNTER (0x13) -#define BCM54213PE_RECEIVE_NOT_OK_COUNTER (0x14) - -#define BCM54213PE_VERSION_B1 (0x600d84a2) -#define BCM54213PE_VERSION_X (0x600d84a0) - -//BCM54213PE_MII_CONTROL -#define MII_CONTROL_PHY_RESET (1 << 15) -#define MII_CONTROL_AUTO_NEGOTIATION_ENABLED (1 << 12) -#define MII_CONTROL_AUTO_NEGOTIATION_RESTART (1 << 9) -#define MII_CONTROL_PHY_FULL_DUPLEX (1 << 8) -#define MII_CONTROL_SPEED_SELECTION (1 << 6) - -//BCM54213PE_MII_STATUS -#define MII_STATUS_LINK_UP (1 << 2) - -//BCM54213PE_CONTROL -#define CONTROL_FULL_DUPLEX_CAPABILITY (1 << 9) -#define CONTROL_HALF_DUPLEX_CAPABILITY (1 << 8) - -#define SPEED_1000 (1000) -#define SPEED_100 (100) -#define SPEED_10 (10) - -#endif/* __DRV_ETH_H__ */ diff --git a/bsp/raspberry-pi/raspi4-64/driver/drv_gpio.c b/bsp/raspberry-pi/raspi4-64/driver/drv_gpio.c deleted file mode 100644 index 8877f626ef..0000000000 --- a/bsp/raspberry-pi/raspi4-64/driver/drv_gpio.c +++ /dev/null @@ -1,187 +0,0 @@ -/* - * Copyright (c) 2006-2021, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2020-04-16 bigmagic first version - */ - -#include "drv_gpio.h" - -#ifdef BSP_USING_PIN - -uint32_t raspi_get_pin_state(uint32_t fselnum) -{ - uint32_t gpfsel = 0; - - switch (fselnum) - { - case 0: - gpfsel = GPIO_REG_GPFSEL0(GPIO_BASE); - break; - case 1: - gpfsel = GPIO_REG_GPFSEL1(GPIO_BASE); - break; - case 2: - gpfsel = GPIO_REG_GPFSEL2(GPIO_BASE); - break; - case 3: - gpfsel = GPIO_REG_GPFSEL3(GPIO_BASE); - break; - case 4: - gpfsel = GPIO_REG_GPFSEL4(GPIO_BASE); - break; - case 5: - gpfsel = GPIO_REG_GPFSEL5(GPIO_BASE); - break; - default: - break; - } - return gpfsel; -} - -void raspi_set_pin_state(uint32_t fselnum, uint32_t gpfsel) -{ - switch (fselnum) - { - case 0: - GPIO_REG_GPFSEL0(GPIO_BASE) = gpfsel; - break; - case 1: - GPIO_REG_GPFSEL1(GPIO_BASE) = gpfsel; - break; - case 2: - GPIO_REG_GPFSEL2(GPIO_BASE) = gpfsel; - break; - case 3: - GPIO_REG_GPFSEL3(GPIO_BASE) = gpfsel; - break; - case 4: - GPIO_REG_GPFSEL4(GPIO_BASE) = gpfsel; - break; - case 5: - GPIO_REG_GPFSEL5(GPIO_BASE) = gpfsel; - break; - default: - break; - } -} - -static void raspi_pin_mode(struct rt_device *dev, rt_base_t pin, rt_base_t mode) -{ - uint32_t fselnum = pin / 10; - uint32_t fselrest = pin % 10; - - uint32_t gpfsel = 0; - gpfsel &= ~((uint32_t)(0x07 << (fselrest * 3))); - gpfsel |= (uint32_t)(mode << (fselrest * 3)); - - switch (fselnum) - { - case 0: - GPIO_REG_GPFSEL0(GPIO_BASE) = gpfsel; - break; - case 1: - GPIO_REG_GPFSEL1(GPIO_BASE) = gpfsel; - break; - case 2: - GPIO_REG_GPFSEL2(GPIO_BASE) = gpfsel; - break; - case 3: - GPIO_REG_GPFSEL3(GPIO_BASE) = gpfsel; - break; - case 4: - GPIO_REG_GPFSEL4(GPIO_BASE) = gpfsel; - break; - case 5: - GPIO_REG_GPFSEL5(GPIO_BASE) = gpfsel; - break; - default: - break; - } -} - -void prev_raspi_pin_mode(GPIO_PIN pin, GPIO_FUNC mode) -{ - uint32_t fselnum = pin / 10; - uint32_t fselrest = pin % 10; - uint32_t gpfsel = 0; - - gpfsel = raspi_get_pin_state(fselnum); - gpfsel &= ~((uint32_t)(0x07 << (fselrest * 3))); - gpfsel |= (uint32_t)(mode << (fselrest * 3)); - raspi_set_pin_state(fselnum, gpfsel); -} - -static void raspi_pin_write(struct rt_device *dev, rt_base_t pin, rt_base_t value) -{ - uint32_t num = pin / 32; - - if(num == 0) - { - if(value == 0) - { - GPIO_REG_GPSET0(GPIO_BASE) = 1 << (pin % 32); - } - else - { - GPIO_REG_GPCLR0(GPIO_BASE) = 1 << (pin % 32); - } - } - else - { - if(value == 0) - { - GPIO_REG_GPSET1(GPIO_BASE) = 1 << (pin % 32); - } - else - { - GPIO_REG_GPCLR1(GPIO_BASE) = 1 << (pin % 32); - } - - } -} - -static int raspi_pin_read(struct rt_device *device, rt_base_t pin) -{ - return 0; -} - -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) -{ - return RT_EOK; -} - -static rt_err_t raspi_pin_detach_irq(struct rt_device *device, rt_int32_t pin) -{ - return RT_EOK; -} - -rt_err_t raspi_pin_irq_enable(struct rt_device *device, rt_base_t pin, rt_uint32_t enabled) -{ - return RT_EOK; -} - -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, - RT_NULL, -}; -#endif - -int rt_hw_gpio_init(void) -{ -#ifdef BSP_USING_PIN - rt_device_pin_register("gpio", &ops, RT_NULL); -#endif - - return 0; -} -INIT_DEVICE_EXPORT(rt_hw_gpio_init); diff --git a/bsp/raspberry-pi/raspi4-64/driver/drv_sdio.h b/bsp/raspberry-pi/raspi4-64/driver/drv_sdio.h deleted file mode 100644 index 78ee02af05..0000000000 --- a/bsp/raspberry-pi/raspi4-64/driver/drv_sdio.h +++ /dev/null @@ -1,268 +0,0 @@ -/* - * Copyright (c) 2006-2021, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2020-10-27 bigmagic first version - */ - -#ifndef __DRV_SDIO_H__ -#define __DRV_SDIO_H__ - -#include -#include -#include - -#include "board.h" -#include "raspi4.h" - -/* Struct for Intrrrupt Information */ -#define SDXC_CmdDone BIT(0) -#define SDXC_DataDone BIT(1) -#define SDXC_BlockGap BIT(2) -#define SDXC_WriteRdy BIT(4) -#define SDXC_ReadRdy BIT(5) -#define SDXC_Card BIT(8) -#define SDXC_Retune BIT(12) -#define SDXC_BootAck BIT(13) -#define SDXC_EndBoot BIT(14) -#define SDXC_Err BIT(15) -#define SDXC_CTOErr BIT(16) -#define SDXC_CCRCErr BIT(17) -#define SDXC_CENDErr BIT(18) -#define SDXC_CBADErr BIT(19) -#define SDXC_DTOErr BIT(20) -#define SDXC_DCRCErr BIT(21) -#define SDXC_DENDErr BIT(22) -#define SDXC_ACMDErr BIT(24) - -#define SDXC_BLKCNT_EN BIT(1) -#define SDXC_AUTO_CMD12_EN BIT(2) -#define SDXC_AUTO_CMD23_EN BIT(3) -#define SDXC_DAT_DIR BIT(4) // from card to host -#define SDXC_MULTI_BLOCK BIT(5) -#define SDXC_CMD_RSPNS_136 BIT(16) -#define SDXC_CMD_RSPNS_48 BIT(17) -#define SDXC_CMD_RSPNS_48busy BIT(16)|BIT(17) -#define SDXC_CHECK_CRC_CMD BIT(19) -#define SDXC_CMD_IXCHK_EN BIT(20) -#define SDXC_CMD_ISDATA BIT(21) -#define SDXC_CMD_SUSPEND BIT(22) -#define SDXC_CMD_RESUME BIT(23) -#define SDXC_CMD_ABORT BIT(23)|BIT(22) - -#define SDXC_CMD_INHIBIT BIT(0) -#define SDXC_DAT_INHIBIT BIT(1) -#define SDXC_DAT_ACTIVE BIT(2) -#define SDXC_WRITE_TRANSFER BIT(8) -#define SDXC_READ_TRANSFER BIT(9) - -struct sdhci_cmd_t -{ - rt_uint32_t cmdidx; - rt_uint32_t cmdarg; - rt_uint32_t resptype; - rt_uint32_t datarw; -#define DATA_READ 1 -#define DATA_WRITE 2 - rt_uint32_t response[4]; -}; - -struct sdhci_data_t -{ - rt_uint8_t *buf; - rt_uint32_t flag; - rt_uint32_t blksz; - rt_uint32_t blkcnt; -}; - -struct sdhci_t -{ - char *name; - rt_uint32_t voltages; - rt_uint32_t width; - rt_uint32_t clock; - rt_err_t removeable; - void *sdcard; - - rt_err_t (*detect)(struct sdhci_t *sdhci); - rt_err_t (*setwidth)(struct sdhci_t *sdhci, rt_uint32_t width); - rt_err_t (*setclock)(struct sdhci_t *sdhci, rt_uint32_t clock); - rt_err_t (*transfer)(struct sdhci_t *sdhci, struct sdhci_cmd_t *cmd, struct sdhci_data_t *dat); - void *priv; -}; - -struct sdhci_pdata_t -{ - size_t virt; -}; - -// EMMC command flags -#define CMD_TYPE_NORMAL (0x00000000) -#define CMD_TYPE_SUSPEND (0x00400000) -#define CMD_TYPE_RESUME (0x00800000) -#define CMD_TYPE_ABORT (0x00c00000) -#define CMD_IS_DATA (0x00200000) -#define CMD_IXCHK_EN (0x00100000) -#define CMD_CRCCHK_EN (0x00080000) -#define CMD_RSPNS_NO (0x00000000) -#define CMD_RSPNS_136 (0x00010000) -#define CMD_RSPNS_48 (0x00020000) -#define CMD_RSPNS_48B (0x00030000) -#define TM_MULTI_BLOCK (0x00000020) -#define TM_DAT_DIR_HC (0x00000000) -#define TM_DAT_DIR_CH (0x00000010) -#define TM_AUTO_CMD23 (0x00000008) -#define TM_AUTO_CMD12 (0x00000004) -#define TM_BLKCNT_EN (0x00000002) -#define TM_MULTI_DATA (CMD_IS_DATA|TM_MULTI_BLOCK|TM_BLKCNT_EN) - -#define RCA_NO (1) -#define RCA_YES (2) - -// INTERRUPT register settings -#define INT_AUTO_ERROR (0x01000000) -#define INT_DATA_END_ERR (0x00400000) -#define INT_DATA_CRC_ERR (0x00200000) -#define INT_DATA_TIMEOUT (0x00100000) -#define INT_INDEX_ERROR (0x00080000) -#define INT_END_ERROR (0x00040000) -#define INT_CRC_ERROR (0x00020000) -#define INT_CMD_TIMEOUT (0x00010000) -#define INT_ERR (0x00008000) -#define INT_ENDBOOT (0x00004000) -#define INT_BOOTACK (0x00002000) -#define INT_RETUNE (0x00001000) -#define INT_CARD (0x00000100) -#define INT_READ_RDY (0x00000020) -#define INT_WRITE_RDY (0x00000010) -#define INT_BLOCK_GAP (0x00000004) -#define INT_DATA_DONE (0x00000002) -#define INT_CMD_DONE (0x00000001) -#define INT_ERROR_MASK \ -( \ - INT_CRC_ERROR | \ - INT_END_ERROR | \ - INT_INDEX_ERROR | \ - INT_DATA_TIMEOUT | \ - INT_DATA_CRC_ERR | \ - INT_DATA_END_ERR | \ - INT_ERR|INT_AUTO_ERROR \ -) - -#define INT_ALL_MASK \ -(\ - INT_CMD_DONE | \ - INT_DATA_DONE | \ - INT_READ_RDY | \ - INT_WRITE_RDY | \ - INT_ERROR_MASK \ -) - -#define EMMC_ARG2 (0x00) -#define EMMC_BLKSIZECNT (0x04) -#define EMMC_ARG1 (0x08) -#define EMMC_CMDTM (0x0c) -#define EMMC_RESP0 (0x10) -#define EMMC_RESP1 (0x14) -#define EMMC_RESP2 (0x18) -#define EMMC_RESP3 (0x1c) -#define EMMC_DATA (0x20) -#define EMMC_STATUS (0x24) -#define EMMC_CONTROL0 (0x28) -#define EMMC_CONTROL1 (0x2c) -#define EMMC_INTERRUPT (0x30) -#define EMMC_IRPT_MASK (0x34) -#define EMMC_IRPT_EN (0x38) -#define EMMC_CONTROL2 (0x3c) -#define EMMC_CAPABILITIES_0 (0x40) -#define EMMC_CAPABILITIES_1 (0x44) -#define EMMC_BOOT_TIMEOUT (0x70) -#define EMMC_EXRDFIFO_EN (0x84) -#define EMMC_SPI_INT_SPT (0xf0) -#define EMMC_SLOTISR_VER (0xfc) - -// CONTROL register settings -#define C0_SPI_MODE_EN (0x00100000) -#define C0_HCTL_HS_EN (0x00000004) -#define C0_HCTL_DWITDH (0x00000002) - -#define C1_SRST_DATA (0x04000000) -#define C1_SRST_CMD (0x02000000) -#define C1_SRST_HC (0x01000000) -#define C1_TOUNIT_DIS (0x000f0000) -#define C1_TOUNIT_MAX (0x000e0000) -#define C1_CLK_GENSEL (0x00000020) -#define C1_CLK_EN (0x00000004) -#define C1_CLK_STABLE (0x00000002) -#define C1_CLK_INTLEN (0x00000001) - -#define FREQ_SETUP (400000) // 400 Khz -#define FREQ_NORMAL (25000000) // 25 Mhz - -// SLOTISR_VER values -#define HOST_SPEC_NUM 0x00ff0000 -#define HOST_SPEC_NUM_SHIFT 16 -#define HOST_SPEC_V3 2 -#define HOST_SPEC_V2 1 -#define HOST_SPEC_V1 0 - -// STATUS register settings -#define SR_DAT_LEVEL1 (0x1e000000) -#define SR_CMD_LEVEL (0x01000000) -#define SR_DAT_LEVEL0 (0x00f00000) -#define SR_DAT3 (0x00800000) -#define SR_DAT2 (0x00400000) -#define SR_DAT1 (0x00200000) -#define SR_DAT0 (0x00100000) -#define SR_WRITE_PROT (0x00080000) // From SDHC spec v2, BCM says reserved -#define SR_READ_AVAILABLE (0x00000800) // ???? undocumented -#define SR_WRITE_AVAILABLE (0x00000400) // ???? undocumented -#define SR_READ_TRANSFER (0x00000200) -#define SR_WRITE_TRANSFER (0x00000100) -#define SR_DAT_ACTIVE (0x00000004) -#define SR_DAT_INHIBIT (0x00000002) -#define SR_CMD_INHIBIT (0x00000001) - -#define CONFIG_MMC_USE_DMA -#define DMA_ALIGN (32U) - -#define SD_CMD_INDEX(a) ((a) << 24) -#define SD_CMD_RESERVED(a) (0xffffffff) -#define SD_CMD_INDEX(a) ((a) << 24) -#define SD_CMD_TYPE_NORMAL (0x0) -#define SD_CMD_TYPE_SUSPEND (1 << 22) -#define SD_CMD_TYPE_RESUME (2 << 22) -#define SD_CMD_TYPE_ABORT (3 << 22) -#define SD_CMD_TYPE_MASK (3 << 22) -#define SD_CMD_ISDATA (1 << 21) -#define SD_CMD_IXCHK_EN (1 << 20) -#define SD_CMD_CRCCHK_EN (1 << 19) -#define SD_CMD_RSPNS_TYPE_NONE (0) // For no response -#define SD_CMD_RSPNS_TYPE_136 (1 << 16) // For response R2 (with CRC), R3,4 (no CRC) -#define SD_CMD_RSPNS_TYPE_48 (2 << 16) // For responses R1, R5, R6, R7 (with CRC) -#define SD_CMD_RSPNS_TYPE_48B (3 << 16) // For responses R1b, R5b (with CRC) -#define SD_CMD_RSPNS_TYPE_MASK (3 << 16) -#define SD_CMD_MULTI_BLOCK (1 << 5) -#define SD_CMD_DAT_DIR_HC (0) -#define SD_CMD_DAT_DIR_CH (1 << 4) -#define SD_CMD_AUTO_CMD_EN_NONE (0) -#define SD_CMD_AUTO_CMD_EN_CMD12 (1 << 2) -#define SD_CMD_AUTO_CMD_EN_CMD23 (2 << 2) -#define SD_CMD_BLKCNT_EN (1 << 1) -#define SD_CMD_DMA (1) -#define SD_RESP_NONE SD_CMD_RSPNS_TYPE_NONE -#define SD_RESP_R1 (SD_CMD_RSPNS_TYPE_48) -#define SD_RESP_R1b (SD_CMD_RSPNS_TYPE_48B) -#define SD_RESP_R2 (SD_CMD_RSPNS_TYPE_136) -#define SD_RESP_R3 SD_CMD_RSPNS_TYPE_48 -#define SD_RESP_R4 SD_CMD_RSPNS_TYPE_136 -#define SD_RESP_R5 (SD_CMD_RSPNS_TYPE_48 | SD_CMD_CRCCHK_EN) -#define SD_RESP_R5b (SD_CMD_RSPNS_TYPE_48B | SD_CMD_CRCCHK_EN) -#define SD_RESP_R6 (SD_CMD_RSPNS_TYPE_48 | SD_CMD_CRCCHK_EN) -#define SD_RESP_R7 (SD_CMD_RSPNS_TYPE_48 | SD_CMD_CRCCHK_EN) -#define SD_DATA_READ (SD_CMD_ISDATA | SD_CMD_DAT_DIR_CH) -#define SD_DATA_WRITE (SD_CMD_ISDATA | SD_CMD_DAT_DIR_HC) -#endif diff --git a/bsp/raspberry-pi/raspi4-64/driver/mbox.h b/bsp/raspberry-pi/raspi4-64/driver/mbox.h deleted file mode 100644 index c3c73c339f..0000000000 --- a/bsp/raspberry-pi/raspi4-64/driver/mbox.h +++ /dev/null @@ -1,188 +0,0 @@ -/* - * Copyright (c) 2006-2021, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2020-09-10 bigmagic first version - */ - -#ifndef __MBOX_H__ -#define __MBOX_H__ - -#include -#include - -// https://github.com/raspberrypi/firmware/wiki/Mailbox-property-interface -// https://github.com/hermanhermitage/videocoreiv - -/* a properly aligned buffer */ -extern volatile unsigned int *mbox; - -#define MBOX_REQUEST 0 - -/* channels */ -#define MBOX_CH_POWER 0 -#define MBOX_CH_FB 1 -#define MBOX_CH_VUART 2 -#define MBOX_CH_VCHIQ 3 -#define MBOX_CH_LEDS 4 -#define MBOX_CH_BTNS 5 -#define MBOX_CH_TOUCH 6 -#define MBOX_CH_COUNT 7 -#define MBOX_CH_PROP 8 - -/* tags */ -#define MBOX_TAG_SETPOWER 0x28001 -#define MBOX_TAG_SETCLKRATE 0x38002 -#define MBOX_GET_MAC_ADDRESS 0x10003 -#define MBOX_TAG_LAST 0 - -#define MMIO_BASE 0xFE000000 -#define VIDEOCORE_MBOX (MMIO_BASE+0x0000B880) -#define MBOX_READ ((volatile unsigned int*)(VIDEOCORE_MBOX+0x0)) -#define MBOX_POLL ((volatile unsigned int*)(VIDEOCORE_MBOX+0x10)) -#define MBOX_SENDER ((volatile unsigned int*)(VIDEOCORE_MBOX+0x14)) -#define MBOX_STATUS ((volatile unsigned int*)(VIDEOCORE_MBOX+0x18)) -#define MBOX_CONFIG ((volatile unsigned int*)(VIDEOCORE_MBOX+0x1C)) -#define MBOX_WRITE ((volatile unsigned int*)(VIDEOCORE_MBOX+0x20)) -#define MBOX_RESPONSE 0x80000000 -#define MBOX_FULL 0x80000000 -#define MBOX_EMPTY 0x40000000 - -#define DEVICE_ID_SD_CARD (0) -#define DEVICE_ID_USB_HCD (3) -#define POWER_STATE_OFF (0 << 0) -#define POWER_STATE_ON (1 << 0) -#define POWER_STATE_WAIT (1 << 1) -#define POWER_STATE_NO_DEVICE (1 << 1) // in response -#define MMU_ENABLE (1) -#define MMU_DISABLE (0) - -/* - * raspi hardware info - */ -enum -{ - MBOX_TAG_HARDWARE_GET_MODEL = 0x00010001, - MBOX_TAG_HARDWARE_GET_REV = 0x00010002, - MBOX_TAG_HARDWARE_GET_MAC_ADDRESS = 0x00010003, - MBOX_TAG_HARDWARE_GET_SERIAL = 0x00010004, - MBOX_TAG_HARDWARE_GET_ARM_MEMORY = 0x00010005, - MBOX_TAG_HARDWARE_GET_VC_MEMORY = 0x00010006, - MBOX_TAG_HARDWARE_GET_CLOCKS = 0x00010007, -}; - -/* - * raspi clock - */ -enum -{ - MBOX_TAG_CLOCK_GET_TURBO = 0x00030009, - MBOX_TAG_CLOCK_SET_TURBO = 0x00038009, - MBOX_TAG_CLOCK_GET_STATE = 0x00030001, - MBOX_TAG_CLOCK_SET_STATE = 0x00038001, - MBOX_TAG_CLOCK_GET_RATE = 0x00030002, - MBOX_TAG_CLOCK_SET_RATE = 0x00038002, - MBOX_TAG_CLOCK_GET_MAX_RATE = 0x00030004, - MBOX_TAG_CLOCK_GET_MIN_RATE = 0x00030007, -}; - -/* - * raspi power - */ -enum -{ - MBOX_TAG_POWER_GET_STATE = 0x00020001, - MBOX_TAG_POWER_SET_STATE = 0x00028001, -}; - -/* - * raspi temperature - */ -enum -{ - MBOX_TAG_TEMP_GET = 0x00030006, - MBOX_TAG_TEMP_GET_MAX = 0x0003000A, -}; - -/* - * raspi Memory - */ -enum -{ - MBOX_TAG_ALLOCATE_MEMORY = 0x0003000C, // Memory: Allocates Contiguous Memory On The GPU (Response: Handle) - MBOX_TAG_LOCK_MEMORY = 0x0003000D, // Memory: Unlock Buffer (Response: Status) - MBOX_TAG_UNLOCK_MEMORY = 0x0003000E, // Memory: Unlock Buffer (Response: Status) - MBOX_TAG_RELEASE_MEMORY = 0x0003000F, // Memory: Free The Memory Buffer (Response: Status) - MBOX_TAG_EXECUTE_CODE = 0x00030010, // Memory: Calls The Function At Given (Bus) Address And With Arguments Given -}; - -/* - * raspi GPU - */ -enum -{ - MBOX_TAG_EXECUTE_QPU = 0x00030011, // QPU: Calls The QPU Function At Given (Bus) Address And With Arguments Given - // (Response: Number Of QPUs, Control, No Flush, Timeout In ms) - MBOX_TAG_ENABLE_QPU = 0x00030012, // QPU: Enables The QPU (Response: Enable State) -}; - -/* - * raspi HDMI - */ -#define MBOX_TAG_GET_EDID_BLOCK 0x00030020 // HDMI: Read Specificed EDID Block From Attached HDMI/DVI Device -// (Response: Block Number, Status, EDID Block (128 Bytes)) - -/* - * raspi NOTIFY - */ -#define MBOX_TAG_NOTIFY_REBOOT 0x00030048 -#define MBOX_TAG_NOTIFY_XHCI_RESET 0x00030058 - -/* -* touch -*/ -#define MBOX_TAG_GET_TOUCHBUF (0x0004000F) - -#define MBOX_ADDR 0x08000000 - -#define RES_CLK_ID (0x000000000) -#define EMMC_CLK_ID (0x000000001) -#define UART_CLK_ID (0x000000002) -#define ARM_CLK_ID (0x000000003) -#define CORE_CLK_ID (0x000000004) -#define V3D_CLK_ID (0x000000005) -#define H264_CLK_ID (0x000000006) -#define ISP_CLK_ID (0x000000007) -#define SDRAM_CLK_ID (0x000000008) -#define PIXEL_CLK_ID (0x000000009) -#define PWM_CLK_ID (0x00000000a) - -int mbox_call(unsigned char ch, int mmu_enable); -int bcm271x_mbox_poweroff_devices(int id); -int bcm271x_mbox_get_touch(void); -int bcm271x_notify_reboot(void); -int bcm271x_notify_xhci_reset(void); -int bcm271x_gpu_enable(void); -int bcm271x_mbox_hardware_get_model(void); -int bcm271x_mbox_hardware_get_revison(void); -int bcm271x_mbox_hardware_get_mac_address(uint8_t *mac); -int bcm271x_mbox_hardware_get_serial(rt_uint64_t *sn); -int bcm271x_mbox_hardware_get_arm_memory(rt_uint32_t *base, rt_uint32_t *size); -int bcm271x_mbox_hardware_get_vc_memory(rt_uint32_t *base, rt_uint32_t *size); -int bcm271x_mbox_clock_get_turbo(void); -int bcm271x_mbox_clock_set_turbo(int level); -int bcm271x_mbox_clock_get_state(int id); -int bcm271x_mbox_clock_set_state(int id, int state); -int bcm271x_mbox_clock_get_rate(int id); -int bcm271x_mbox_clock_set_rate(int id, int rate); -int bcm271x_mbox_clock_get_max_rate(int id); -int bcm271x_mbox_clock_get_min_rate(int id); -int bcm271x_mbox_power_get_state(int id); -int bcm271x_mbox_power_set_state(int id, int state); -int bcm271x_mbox_temp_get(void); -int bcm271x_mbox_temp_get_max(void); - -#endif diff --git a/bsp/raspberry-pi/raspi4-64/driver/raspi4.h b/bsp/raspberry-pi/raspi4-64/driver/raspi4.h deleted file mode 100644 index 02cceab4aa..0000000000 --- a/bsp/raspberry-pi/raspi4-64/driver/raspi4.h +++ /dev/null @@ -1,167 +0,0 @@ -#ifndef __RASPI4_H__ -#define __RASPI4_H__ - -#include - -#define __REG32(x) (*((volatile unsigned int *)(x))) - -//base address -#define PER_BASE (0xFE000000) - -//gpio offset -#define GPIO_BASE_OFFSET (0x00200000) - -//pl011 offset -#define PL011_UART_BASE_OFFSET (0x00201000) - -//pactl cs offset -#define PACTL_CS_OFFSET (0x00204E00) - -//aux offset -#define AUX_BASE_OFFSET (0x00215000) - -//gpio -#define GPIO_BASE (PER_BASE + GPIO_BASE_OFFSET) -#define GPIO_IRQ_NUM (3) //40 pin mode -#define IRQ_GPIO0 (96 + 49) //bank0 (0 to 27) -#define IRQ_GPIO1 (96 + 50) //bank1 (28 to 45) -#define IRQ_GPIO2 (96 + 51) //bank2 (46 to 57) -#define IRQ_GPIO3 (96 + 52) //bank3 - -//system timer -#define ARM_TIMER_IRQ (64) -#define ARM_TIMER_BASE (PER_BASE + 0xB000) -#define ARM_TIMER_LOAD HWREG32(ARM_TIMER_BASE + 0x400) -#define ARM_TIMER_VALUE HWREG32(ARM_TIMER_BASE + 0x404) -#define ARM_TIMER_CTRL HWREG32(ARM_TIMER_BASE + 0x408) -#define ARM_TIMER_IRQCLR HWREG32(ARM_TIMER_BASE + 0x40C) -#define ARM_TIMER_RAWIRQ HWREG32(ARM_TIMER_BASE + 0x410) -#define ARM_TIMER_MASKIRQ HWREG32(ARM_TIMER_BASE + 0x414) -#define ARM_TIMER_RELOAD HWREG32(ARM_TIMER_BASE + 0x418) -#define ARM_TIMER_PREDIV HWREG32(ARM_TIMER_BASE + 0x41C) -#define ARM_TIMER_CNTR HWREG32(ARM_TIMER_BASE + 0x420) - -//uart -#define UART_BASE (PER_BASE + PL011_UART_BASE_OFFSET) -#define UART0_BASE (UART_BASE + 0x0) -#define UART2_BASE (UART_BASE + 0x400) -#define UART3_BASE (UART_BASE + 0x600) -#define UART4_BASE (UART_BASE + 0x800) -#define UART5_BASE (UART_BASE + 0xA00) -#define IRQ_AUX_UART (96 + 29) -#define UART_REFERENCE_CLOCK (48000000) - -//aux -#define AUX_BASE (PER_BASE + AUX_BASE_OFFSET) -#define IRQ_PL011 (96 + 57) - -//pactl cs -#define PACTL_CS_ADDR (PER_BASE + PACTL_CS_OFFSET) -#define PACTL_CS HWREG32(PACTL_CS_ADDR) -typedef enum -{ - IRQ_SPI0 = 0x00000000, - IRQ_SPI1 = 0x00000002, - IRQ_SPI2 = 0x00000004, - IRQ_SPI3 = 0x00000008, - IRQ_SPI4 = 0x00000010, - IRQ_SPI5 = 0x00000020, - IRQ_SPI6 = 0x00000040, - IRQ_I2C0 = 0x00000100, - IRQ_I2C1 = 0x00000200, - IRQ_I2C2 = 0x00000400, - IRQ_I2C3 = 0x00000800, - IRQ_I2C4 = 0x00001000, - IRQ_I2C5 = 0x00002000, - IRQ_I2C6 = 0x00004000, - IRQ_I2C7 = 0x00008000, - IRQ_UART5 = 0x00010000, - IRQ_UART4 = 0x00020000, - IRQ_UART3 = 0x00040000, - IRQ_UART2 = 0x00080000, - IRQ_UART0 = 0x00100000 -} PACTL_CS_VAL; - -// 0x40, 0x44, 0x48, 0x4c: Core 0~3 Timers interrupt control -#define CORE_TIMER_IRQ_CTRL(n) HWREG32((unsigned long)(0xFF800040 + (n) * 4)) -#define TIMER_IRQ 30 -#define NON_SECURE_TIMER_IRQ (1 << 1) -rt_inline void core_timer_enable(int cpu_id) -{ - CORE_TIMER_IRQ_CTRL(cpu_id) |= NON_SECURE_TIMER_IRQ; -} - -//core timer -#define ST_BASE_OFFSET (0x003000) -#define STIMER_BASE (PER_BASE + ST_BASE_OFFSET) -#define STIMER_CS HWREG32(STIMER_BASE + 0x0000) -#define STIMER_CLO HWREG32(STIMER_BASE + 0x0004) -#define STIMER_CHI HWREG32(STIMER_BASE + 0x0008) -#define STIMER_C0 HWREG32(STIMER_BASE + 0x000C) -#define STIMER_C1 HWREG32(STIMER_BASE + 0x0010) -#define STIMER_C2 HWREG32(STIMER_BASE + 0x0014) -#define STIMER_C3 HWREG32(STIMER_BASE + 0x0018) - -#define DELAY_MICROS(micros) \ -do { \ - rt_uint32_t compare = STIMER_CLO + micros * 25; \ - while (STIMER_CLO < compare); \ -} while (0) \ - -//mmc -#define MMC0_BASE_ADDR (PER_BASE + 0x300000) -#define MMC2_BASE_ADDR (PER_BASE + 0x340000) - -//eth -#define MAC_BASE_ADDR (0xfd580000) -#define MAC_REG_BASE_ADDR (void *)(MAC_BASE_ADDR) -#define ETH_IRQ (160 + 29) -#define SEND_DATA_NO_CACHE (0x08200000) -#define RECV_DATA_NO_CACHE (0x08400000) - -//watchdog -#define WDT_BASE (PER_BASE + 0x00100000) -#define PM_RSTC HWREG32(WDT_BASE + 0x0000001c) -#define PM_RSTS HWREG32(WDT_BASE + 0x00000020) -#define PM_WDOG HWREG32(WDT_BASE + 0x00000024) - -#define PM_PASSWORD (0x5A000000) -#define PM_WDOG_TIME_SET (0x000fffff) -#define PM_RSTS_HADWRH_SET (0x00000040) -#define PM_RSTC_WRCFG_FULL_RESET (0x00000020) -#define PM_RSTC_WRCFG_CLR (0xffffffcf) -#define PM_RSTC_RESET (0x00000102) - -//gic max -#define MAX_HANDLERS (256) -#define ARM_GIC_NR_IRQS (512) -#define INTC_BASE (0xff800000) -#define ARM_GIC_MAX_NR (512) -#define GIC_V2_BASE (INTC_BASE + 0x00040000) -#define GIC_V2_DISTRIBUTOR_BASE (INTC_BASE + 0x00041000) -#define GIC_V2_CPU_INTERFACE_BASE (INTC_BASE + 0x00042000) -#define GIC_V2_HYPERVISOR_BASE (INTC_BASE + 0x00044000) -#define GIC_V2_VIRTUAL_CPU_BASE (INTC_BASE + 0x00046000) - -/* ipi interrupt number */ -#define IRQ_ARM_IPI_KICK 0 -#define IRQ_ARM_IPI_CALL 1 - -#define GIC_IRQ_START 0 -#define GIC_ACK_INTID_MASK 0x000003ff - -#define GIC_PL400_DISTRIBUTOR_PPTR GIC_V2_DISTRIBUTOR_BASE -#define GIC_PL400_CONTROLLER_PPTR GIC_V2_CPU_INTERFACE_BASE - -/* the basic constants and interfaces needed by gic */ -rt_inline rt_uint32_t platform_get_gic_dist_base(void) -{ - return GIC_PL400_DISTRIBUTOR_PPTR; -} - -rt_inline rt_uint32_t platform_get_gic_cpu_base(void) -{ - return GIC_PL400_CONTROLLER_PPTR; -} - -#endif diff --git a/bsp/raspberry-pi/raspi4-64/driver/Kconfig b/bsp/raspberry-pi/raspi4-64/drivers/Kconfig similarity index 69% rename from bsp/raspberry-pi/raspi4-64/driver/Kconfig rename to bsp/raspberry-pi/raspi4-64/drivers/Kconfig index 9209c0ae24..ddd175764f 100644 --- a/bsp/raspberry-pi/raspi4-64/driver/Kconfig +++ b/bsp/raspberry-pi/raspi4-64/drivers/Kconfig @@ -1,3 +1,12 @@ + +config BSP_SUPPORT_FPU + bool "Using Float" + default n + +menuconfig BSP_USING_VM_MODE + bool "Enable VM mode" + default n + menu "Hardware Drivers Config" menu "BCM Peripheral Drivers" menuconfig BSP_USING_UART @@ -26,20 +35,44 @@ menu "Hardware Drivers Config" bool "Enable UART 5" default n endif - - config BSP_USING_GIC - bool + + menuconfig BSP_USING_GIC + bool "Enable GIC" + select RT_USING_GIC default y - + if BSP_USING_GIC config BSP_USING_GICV2 - bool + bool "Enable GIC400(GICV2)" default y + config BSP_USING_GICV3 + bool "Enable GIC500(GICV3)" + default n + endif config BSP_USING_PIN bool "Using PIN" select RT_USING_PIN default y + 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_CORETIMER bool "Using core timer" select RT_USING_CORETIMER @@ -59,10 +92,6 @@ menu "Hardware Drivers Config" default n endif - config BSP_USING_ETH - bool "Enable ETH" - default n - config BSP_USING_WDT bool "Enable WDT" select RT_USING_WDT @@ -103,5 +132,9 @@ menu "Hardware Drivers Config" bool "HDMI DISPLAY" default n endif + + menuconfig BSP_USING_TOUCH + bool "Enable Touch" + default n endmenu endmenu diff --git a/bsp/raspberry-pi/raspi4-64/drivers/SConscript b/bsp/raspberry-pi/raspi4-64/drivers/SConscript new file mode 100644 index 0000000000..98c38943e9 --- /dev/null +++ b/bsp/raspberry-pi/raspi4-64/drivers/SConscript @@ -0,0 +1,19 @@ +from building import * + +cwd = GetCurrentDir() +src = Glob('*.c') + Glob('*.cpp') + Glob('*.S') +CPPPATH = [cwd, str(Dir('#'))] + +group = DefineGroup('driver', src, depend = [''], CPPPATH = CPPPATH) + +# build for sub-directory +list = os.listdir(cwd) +objs = [] + +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')) +group = group + objs + +Return('group') diff --git a/bsp/raspberry-pi/raspi4-64/drivers/board.c b/bsp/raspberry-pi/raspi4-64/drivers/board.c new file mode 100644 index 0000000000..7c84153117 --- /dev/null +++ b/bsp/raspberry-pi/raspi4-64/drivers/board.c @@ -0,0 +1,245 @@ +/* + * Copyright (c) 2006-2020, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2020-04-16 bigmagic first version + * 2021-12-28 GuEe-GUI add smp support + * 2023-03-28 WangXiaoyao sync works & memory layout fixups + * code formats + */ + +#include +#include +#include + +#include "board.h" +#include "drv_uart.h" + +#include "cp15.h" +#include "mmu.h" +#include "mbox.h" +#include + +#ifdef RT_USING_SMART +#include +#endif + +extern size_t MMUTable[]; + +size_t gpio_base_addr = GPIO_BASE_ADDR; + +size_t uart_base_addr = UART_BASE; + +size_t gic_base_addr = GIC_V2_BASE; + +size_t arm_timer_base = ARM_TIMER_BASE; + +size_t pactl_cs_base = PACTL_CS_ADDR; + +size_t stimer_base_addr = STIMER_BASE; + +size_t mmc2_base_addr = MMC2_BASE_ADDR; + +size_t videocore_mbox = VIDEOCORE_MBOX; + +size_t mbox_addr = MBOX_ADDR; + +size_t wdt_base_addr = WDT_BASE; + +uint8_t *mac_reg_base_addr = (uint8_t *)MAC_REG; + +uint8_t *eth_send_no_cache = (uint8_t *)SEND_DATA_NO_CACHE; +uint8_t *eth_recv_no_cache = (uint8_t *)RECV_DATA_NO_CACHE; + +#ifdef RT_USING_SMART +struct mem_desc platform_mem_desc[] = { + {KERNEL_VADDR_START, KERNEL_VADDR_START + 0x0fffffff, (rt_size_t)ARCH_MAP_FAILED, NORMAL_MEM} +}; +#else +struct mem_desc platform_mem_desc[] = { + {0x00200000, (128ul << 20) - 1, 0x00200000, NORMAL_MEM}, + {0xFC000000, 0x000100000000 - 1, 0xFC000000, DEVICE_MEM}, +}; +#endif + +const rt_uint32_t platform_mem_desc_size = sizeof(platform_mem_desc)/sizeof(platform_mem_desc[0]); + +void idle_wfi(void) +{ + asm volatile ("wfi"); +} + +/** + * This function will initialize board + */ + +extern size_t MMUTable[]; +int rt_hw_gtimer_init(void); + +rt_region_t init_page_region = { + PAGE_START, + PAGE_END, +}; + +/** + * Initialize the Hardware related stuffs. Called from rtthread_startup() + * after interrupt disabled. + */ +void rt_hw_board_init(void) +{ + extern void (*system_off)(void); + extern void reboot(void); + system_off = reboot; + + /* io device remap */ +#ifdef RT_USING_SMART + rt_hw_mmu_map_init(&rt_kernel_space, (void*)0xfffffffff0000000, 0x10000000, MMUTable, PV_OFFSET); +#else + rt_hw_mmu_map_init(&rt_kernel_space, (void*)0x000400000000, 0x10000000, MMUTable, 0); +#endif + rt_page_init(init_page_region); + rt_hw_mmu_setup(&rt_kernel_space, platform_mem_desc, platform_mem_desc_size); + + /* map peripheral address to virtual address */ +#ifdef RT_USING_HEAP + /* initialize system heap */ + rt_system_heap_init((void *)HEAP_BEGIN, (void *)HEAP_END); +#endif + + /* initialize hardware interrupt */ + rt_hw_interrupt_init(); + + //gpio + gpio_base_addr = (size_t)rt_ioremap((void*)GPIO_BASE_ADDR, 0x1000); + + //pactl + pactl_cs_base = (size_t)rt_ioremap((void*)PACTL_CS_ADDR, 0x1000); + + //stimer + stimer_base_addr = (size_t)rt_ioremap((void*)STIMER_BASE, 0x1000); + + //mmc2_base_addr + mmc2_base_addr = (size_t)rt_ioremap((void*)MMC2_BASE_ADDR, 0x1000); + + //mbox + videocore_mbox = (size_t)rt_ioremap((void*)VIDEOCORE_MBOX, 0x1000); + + // mbox msg + mbox = (volatile unsigned int *)rt_pages_alloc(0); + + //wdt + wdt_base_addr = (size_t)rt_ioremap((void*)WDT_BASE, 0x1000); + + //mac + mac_reg_base_addr = (void *)rt_ioremap((void*)MAC_REG, 0x80000); + + // eth data + eth_send_no_cache = (void *)rt_pages_alloc(rt_page_bits(0x200000)); + eth_recv_no_cache = (void *)rt_pages_alloc(rt_page_bits(0x200000)); + + /* initialize uart */ + rt_hw_uart_init(); + + /* initialize timer for os tick */ + rt_hw_gtimer_init(); + +#ifdef RT_USING_CONSOLE + /* set console device */ + rt_console_set_device(RT_CONSOLE_DEVICE_NAME); +#endif /* RT_USING_CONSOLE */ + + rt_kprintf("heap: 0x%08x - 0x%08x\n", HEAP_BEGIN, HEAP_END); + +#ifdef RT_USING_COMPONENTS_INIT + rt_components_board_init(); +#endif + rt_thread_idle_sethook(idle_wfi); +} + +#ifdef RT_USING_SMP +#include + +void rt_hw_mmu_ktbl_set(unsigned long tbl); +void _secondary_cpu_entry(void); + +static unsigned long cpu_release_paddr[] = +{ + [0] = 0xd8, + [1] = 0xe0, + [2] = 0xe8, + [3] = 0xf0, + [4] = 0x00 +}; + +#ifndef RT_USING_SMART +static void *_remap(void *paddr, size_t size) +{ + int ret; + static void *va = 0; + size_t low_off = (size_t)paddr & ARCH_PAGE_MASK; + if (va) + return va + low_off; + + va = rt_kernel_space.start; + while (1) + { + int rt_kmem_map_phy(void *va, void *pa, rt_size_t length, rt_size_t attr); + ret = rt_kmem_map_phy(va, 0x0, ARCH_PAGE_SIZE, MMU_MAP_K_DEVICE); + if (ret == RT_EOK) + { + break; + } + else + { + va += ARCH_PAGE_SIZE; + } + } + return va + low_off; +} +#endif /* RT_USING_SMART */ + +void rt_hw_secondary_cpu_up(void) +{ + int i; + void *release_addr; + + for (i = 1; i < RT_CPUS_NR && cpu_release_paddr[i]; ++i) + { +#ifdef RT_USING_SMART + release_addr = rt_ioremap((void *)cpu_release_paddr[i], sizeof(cpu_release_paddr[0])); +#else + release_addr = _remap((void *)cpu_release_paddr[i], sizeof(cpu_release_paddr[0])); +#endif + __asm__ volatile ("str %0, [%1]"::"rZ"((unsigned long)_secondary_cpu_entry + PV_OFFSET), "r"(release_addr)); + rt_hw_cpu_dcache_ops(RT_HW_CACHE_FLUSH, release_addr, sizeof(release_addr)); + asm volatile ("dsb sy"); + asm volatile ("sev"); + } +} + +void rt_hw_secondary_cpu_bsp_start(void) +{ + rt_hw_spin_lock(&_cpus_lock); + + rt_hw_mmu_ktbl_set((unsigned long)MMUTable); + + rt_hw_vector_init(); + + arm_gic_cpu_init(0, 0); + + rt_hw_gtimer_init(); + + rt_kprintf("\rcpu %d boot success\n", rt_hw_cpu_id()); + + rt_system_scheduler_start(); +} + +void rt_hw_secondary_cpu_idle_exec(void) +{ + asm volatile ("wfe":::"memory", "cc"); +} + +#endif diff --git a/bsp/raspberry-pi/raspi4-64/drivers/board.h b/bsp/raspberry-pi/raspi4-64/drivers/board.h new file mode 100644 index 0000000000..9bab322395 --- /dev/null +++ b/bsp/raspberry-pi/raspi4-64/drivers/board.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2006-2020, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2020-04-16 bigmagic first version + */ + +#ifndef BOARD_H__ +#define BOARD_H__ + +#include +#include "raspi4.h" +#include "mmu.h" +#include "ioremap.h" + +extern int __bss_end; +#define HEAP_BEGIN ((void*)&__bss_end) + +#ifdef RT_USING_SMART +#define HEAP_END ((size_t)KERNEL_VADDR_START + 32 * 1024 * 1024) +#define PAGE_START HEAP_END +#define PAGE_END ((size_t)KERNEL_VADDR_START + 128 * 1024 * 1024) +#else +#define KERNEL_VADDR_START 0x0 + +#define HEAP_END (KERNEL_VADDR_START + 64 * 1024 * 1024) +#define PAGE_START HEAP_END +#define PAGE_END ((size_t)PAGE_START + 64 * 1024 * 1024) +#endif + +void rt_hw_board_init(void); + +#endif diff --git a/bsp/raspberry-pi/raspi4-64/drivers/drv_dsi_touch.c b/bsp/raspberry-pi/raspi4-64/drivers/drv_dsi_touch.c new file mode 100644 index 0000000000..33ec901f63 --- /dev/null +++ b/bsp/raspberry-pi/raspi4-64/drivers/drv_dsi_touch.c @@ -0,0 +1,243 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2020-11-26 bigmagic first version + */ +#include +#include +#include +#include +#include + +#ifdef RT_USING_SMART +#include +#include +#endif + +#include + +#ifdef BSP_USING_TOUCH + +#include "mbox.h" +#include "drv_dsi_touch.h" + +#define DBG_TAG "dsi_touch" +#define DBG_LVL DBG_INFO +#include + +static rt_touch_t touch_device = RT_NULL; +static struct rt_semaphore dsi_touch_ack; + +static rt_uint32_t touch_x; +static rt_uint32_t touch_y; +static rt_uint32_t touch_state = 0; + +static rt_thread_t dsi_touch_tid = RT_NULL; +#define DSI_TOUCH_THREAD_STACK_SIZE (4096) +#define DSI_TOUCH_THREAD_PRIORITY (25) +#define DSI_TOUCH_THREAD_TIMESLICE (10) + +#define MAXIMUM_SUPPORTED_POINTS (10) + +struct touch_regs +{ + uint8_t device_mode; + uint8_t gesture_id; + uint8_t num_points; + struct touch + { + uint8_t xh; + uint8_t xl; + uint8_t yh; + uint8_t yl; + uint8_t res1; + uint8_t res2; + } point[MAXIMUM_SUPPORTED_POINTS]; +}; + +struct drv_mouse_device +{ + struct rt_device parent; + struct rt_touch_data touchdata; + int channel; +}; + +struct drv_mouse_device _mouse; + +static void post_event(rt_uint16_t x, rt_uint16_t y, rt_uint8_t event) +{ + struct rt_touch_data *minfo = &_mouse.touchdata; + struct rt_channel_msg ch_msg; + + LOG_D("event:%d, x:%d, y:%d\n", event, x, y); + + minfo->x_coordinate = x; + minfo->y_coordinate = y; + minfo->event = event; + ch_msg.type = RT_CHANNEL_RAW; + ch_msg.u.d = (void *)(size_t)event; + rt_channel_send(_mouse.channel, &ch_msg); +} + +static void dsi_touch_thread_entry(void *param) +{ + static volatile unsigned long touchbuf; + touchbuf = bcm271x_mbox_get_touch(); + + if (touchbuf == RT_NULL) + { + rt_kprintf("init dsi touch err!\n"); + return; + } + +#ifdef BSP_USING_VM_MODE + if (rt_hv_stage2_map((unsigned long)touchbuf, 0x1000)) + { + rt_kprintf("alloc mmio from hyper fail!\n"); + return; + } +#endif + + touchbuf = (unsigned long)rt_ioremap((void *)touchbuf, 0x1000); + + while (1) + { + struct touch_regs *regs = (struct touch_regs *)touchbuf; + if ((regs->num_points > 0) && (regs->num_points < MAXIMUM_SUPPORTED_POINTS)) + { + /* only one touch point */ + touch_x = (((int)regs->point[0].xh & 0xf) << 8) + regs->point[0].xl; + touch_y = (((int)regs->point[0].yh & 0xf) << 8) + regs->point[0].yl; + if (!touch_state) + { + post_event(touch_x, touch_y, RT_TOUCH_EVENT_DOWN); + } + else + { + post_event(touch_x, touch_y, RT_TOUCH_EVENT_MOVE); + } + touch_state = 1; + } + else + { + if (touch_state) + { + post_event(touch_x, touch_y, RT_TOUCH_EVENT_UP); + } + touch_state = 0; + } + rt_thread_mdelay(1); + } +} + +static rt_size_t dsi_read_point(struct rt_touch_device *touch, void *buf, rt_size_t read_num) +{ + rt_uint16_t* touchxy = (rt_uint16_t *)buf; + + if ((read_num != 0) && (touch_state == 1)) + { + touchxy[0] = touch_x; + touchxy[1] = touch_y; + touch_state = 0; + return read_num; + } + else + { + return 0; + } +} + +static rt_err_t dsi_control(struct rt_touch_device *device, int cmd, void *data) +{ + return RT_EOK; +} + +static struct rt_touch_ops dsi_touch_ops = +{ + .touch_readpoint = dsi_read_point, + .touch_control = dsi_control, +}; + +static rt_err_t drv_mouse_init(struct rt_device *device) +{ + struct drv_mouse_device *mouse = (struct drv_mouse_device*)device; + + return RT_EOK; +} + +static rt_err_t drv_mouse_control(struct rt_device *device, int cmd, void *args) +{ + switch (cmd) + { +#define CMD_MOUSE_SET_NOTIFY 0 /* arg is shmid, in the shm, a sem point is given */ + case CMD_MOUSE_SET_NOTIFY: + *(unsigned long *)args = (rt_uint32_t)(unsigned long)lwp_map_user_phy(lwp_self(), RT_NULL, (uint32_t*)((size_t)&_mouse.touchdata + PV_OFFSET), sizeof(struct rt_touch_data), 1); + break; + default: + break; + } + return RT_EOK; +} + +#ifdef RT_USING_DEVICE_OPS +const static struct rt_device_ops _mouse_ops = +{ + drv_mouse_init, + RT_NULL, + RT_NULL, + RT_NULL, + RT_NULL, + drv_mouse_control +}; +#endif + +static int hw_dsi_touch_init(void) +{ + struct rt_device *device = &_mouse.parent; + +#ifdef RT_USING_DEVICE_OPS + device->ops = &_mouse_ops; +#else + device->init = drv_mouse_init; + device->open = RT_NULL; + device->close = RT_NULL; + device->read = RT_NULL; + device->write = RT_NULL; + device->control = drv_mouse_control; +#endif + rt_device_register(device, "mouse", RT_DEVICE_FLAG_RDWR); + _mouse.channel = rt_channel_open("mouse", O_CREAT); + + /* touch sem */ + rt_sem_init(&dsi_touch_ack, "dsi_touch_ack", 0, RT_IPC_FLAG_FIFO); + + dsi_touch_tid = rt_thread_create("dsi_touch", + dsi_touch_thread_entry, RT_NULL, + DSI_TOUCH_THREAD_STACK_SIZE, + DSI_TOUCH_THREAD_PRIORITY, DSI_TOUCH_THREAD_TIMESLICE); + if (dsi_touch_tid != RT_NULL) + { + rt_thread_startup(dsi_touch_tid); + } + + touch_device = (rt_touch_t)rt_malloc(sizeof(struct rt_touch_device)); + + if (touch_device == RT_NULL) + { + return -RT_ERROR; + } + + /* register touch device */ + touch_device->info.type = RT_TOUCH_TYPE_RESISTANCE; + touch_device->info.vendor = RT_TOUCH_VENDOR_UNKNOWN; + + touch_device->ops = &dsi_touch_ops; + rt_hw_touch_register(touch_device, "dsi_touch", RT_DEVICE_FLAG_INT_RX, RT_NULL); + return 0; +} +INIT_APP_EXPORT(hw_dsi_touch_init); +#endif /* BSP_USING_TOUCH */ diff --git a/bsp/raspberry-pi/raspi4-64/driver/drv_eth.c b/bsp/raspberry-pi/raspi4-64/drivers/drv_eth.c similarity index 57% rename from bsp/raspberry-pi/raspi4-64/driver/drv_eth.c rename to bsp/raspberry-pi/raspi4-64/drivers/drv_eth.c index 5732274246..667e973da3 100644 --- a/bsp/raspberry-pi/raspi4-64/driver/drv_eth.c +++ b/bsp/raspberry-pi/raspi4-64/drivers/drv_eth.c @@ -7,33 +7,30 @@ * Change Logs: * Date Author Notes * 2020-10-30 bigmagic first version + * 2023-03-28 WangXiaoyao Modify pbuf_alloc */ -#include #include #include #include - -#ifdef BSP_USING_ETH - #include #include -#include #include "mbox.h" #include "raspi4.h" #include "drv_eth.h" -#define DBG_LEVEL DBG_LOG +#define DBG_LEVEL DBG_LOG #include -#define LOG_TAG "drv.eth" +#define LOG_TAG "drv.eth" -#define RECV_CACHE_BUF (2048) -#define SEND_CACHE_BUF (2048) -#define DMA_DISC_ADDR_SIZE (2 * 1024 *1024) +static int link_speed = 0; +static int link_flag = 0; -#define RX_DESC_BASE (MAC_REG_BASE_ADDR + GENET_RX_OFF) -#define TX_DESC_BASE (MAC_REG_BASE_ADDR + GENET_TX_OFF) +#define DMA_DISC_ADDR_SIZE (4 * 1024 *1024) + +#define RX_DESC_BASE (mac_reg_base_addr + GENET_RX_OFF) +#define TX_DESC_BASE (mac_reg_base_addr + GENET_TX_OFF) #define MAX_ADDR_LEN (6) @@ -42,20 +39,15 @@ #define BIT(nr) (1UL << (nr)) -#define LINK_THREAD_STACK_SIZE (2048) -#define LINK_THREAD_PRIORITY (20) -#define LINK_THREAD_TIMESLICE (10) - -static int link_speed = 0; -static int link_flag = 0; - static rt_thread_t link_thread_tid = RT_NULL; +#define LINK_THREAD_STACK_SIZE (8192) +#define LINK_THREAD_PRIORITY (20) +#define LINK_THREAD_TIMESLICE (10) static rt_uint32_t tx_index = 0; static rt_uint32_t rx_index = 0; static rt_uint32_t index_flag = 0; - struct rt_eth_dev { struct eth_device parent; @@ -68,29 +60,25 @@ struct rt_eth_dev void *priv; }; static struct rt_eth_dev eth_dev; - -static struct rt_semaphore send_finsh_sem_lock; - static struct rt_semaphore link_ack; -rt_inline rt_uint32_t read32(void *addr) +static inline rt_uint32_t read32(void *addr) { - return (*((volatile unsigned int *)(addr))); + return (*((volatile unsigned int*)(addr))); } -rt_inline void write32(void *addr, rt_uint32_t value) +static inline void write32(void *addr, rt_uint32_t value) { - (*((volatile unsigned int *)(addr))) = value; + (*((volatile unsigned int*)(addr))) = value; } static void eth_rx_irq(int irq, void *param) { rt_uint32_t val = 0; + val = read32(mac_reg_base_addr + GENET_INTRL2_CPU_STAT); + val &= ~read32(mac_reg_base_addr + GENET_INTRL2_CPU_STAT_MASK); - val = read32(MAC_REG_BASE_ADDR + GENET_INTRL2_CPU_STAT); - val &= ~read32(MAC_REG_BASE_ADDR + GENET_INTRL2_CPU_STAT_MASK); - - write32(MAC_REG_BASE_ADDR + GENET_INTRL2_CPU_CLEAR, val); + write32(mac_reg_base_addr + GENET_INTRL2_CPU_CLEAR, val); if (val & GENET_IRQ_RXDMA_DONE) { @@ -99,75 +87,73 @@ static void eth_rx_irq(int irq, void *param) if (val & GENET_IRQ_TXDMA_DONE) { - rt_sem_release(&send_finsh_sem_lock); + //todo } } -/* we only support RGMII (as used on the RPi4) */ +/* We only support RGMII (as used on the RPi4). */ static int bcmgenet_interface_set(void) { int phy_mode = PHY_INTERFACE_MODE_RGMII; - switch (phy_mode) { case PHY_INTERFACE_MODE_RGMII: case PHY_INTERFACE_MODE_RGMII_RXID: - write32(MAC_REG_BASE_ADDR + SYS_PORT_CTRL, PORT_MODE_EXT_GPHY); + write32(mac_reg_base_addr + SYS_PORT_CTRL, PORT_MODE_EXT_GPHY); break; + default: - rt_kprintf("unknown phy mode: %d\n", MAC_REG_BASE_ADDR); + rt_kprintf("unknown phy mode: %d\n", mac_reg_base_addr); return -1; } - return 0; } static void bcmgenet_umac_reset(void) { rt_uint32_t reg; - - reg = read32(MAC_REG_BASE_ADDR + SYS_RBUF_FLUSH_CTRL); + reg = read32(mac_reg_base_addr + SYS_RBUF_FLUSH_CTRL); reg |= BIT(1); - write32((MAC_REG_BASE_ADDR + SYS_RBUF_FLUSH_CTRL), reg); + write32((mac_reg_base_addr + SYS_RBUF_FLUSH_CTRL), reg); reg &= ~BIT(1); - write32((MAC_REG_BASE_ADDR + SYS_RBUF_FLUSH_CTRL), reg); + write32((mac_reg_base_addr + SYS_RBUF_FLUSH_CTRL), reg); DELAY_MICROS(10); - write32((MAC_REG_BASE_ADDR + SYS_RBUF_FLUSH_CTRL), 0); + write32((mac_reg_base_addr + SYS_RBUF_FLUSH_CTRL), 0); DELAY_MICROS(10); - write32(MAC_REG_BASE_ADDR + UMAC_CMD, 0); - write32(MAC_REG_BASE_ADDR + UMAC_CMD, (CMD_SW_RESET | CMD_LCL_LOOP_EN)); + write32(mac_reg_base_addr + UMAC_CMD, 0); + write32(mac_reg_base_addr + UMAC_CMD, (CMD_SW_RESET | CMD_LCL_LOOP_EN)); DELAY_MICROS(2); - write32(MAC_REG_BASE_ADDR + UMAC_CMD, 0); + write32(mac_reg_base_addr + UMAC_CMD, 0); /* clear tx/rx counter */ - write32(MAC_REG_BASE_ADDR + UMAC_MIB_CTRL, MIB_RESET_RX | MIB_RESET_TX | MIB_RESET_RUNT); - write32(MAC_REG_BASE_ADDR + UMAC_MIB_CTRL, 0); - write32(MAC_REG_BASE_ADDR + UMAC_MAX_FRAME_LEN, ENET_MAX_MTU_SIZE); + write32(mac_reg_base_addr + UMAC_MIB_CTRL, MIB_RESET_RX | MIB_RESET_TX | MIB_RESET_RUNT); + write32(mac_reg_base_addr + UMAC_MIB_CTRL, 0); + write32(mac_reg_base_addr + UMAC_MAX_FRAME_LEN, ENET_MAX_MTU_SIZE); /* init rx registers, enable ip header optimization */ - reg = read32(MAC_REG_BASE_ADDR + RBUF_CTRL); + reg = read32(mac_reg_base_addr + RBUF_CTRL); reg |= RBUF_ALIGN_2B; - write32(MAC_REG_BASE_ADDR + RBUF_CTRL, reg); - write32(MAC_REG_BASE_ADDR + RBUF_TBUF_SIZE_CTRL, 1); + write32(mac_reg_base_addr + RBUF_CTRL, reg); + write32(mac_reg_base_addr + RBUF_TBUF_SIZE_CTRL, 1); } static void bcmgenet_disable_dma(void) { rt_uint32_t tdma_reg = 0, rdma_reg = 0; - tdma_reg = read32(MAC_REG_BASE_ADDR + TDMA_REG_BASE + DMA_CTRL); + tdma_reg = read32(mac_reg_base_addr + TDMA_REG_BASE + DMA_CTRL); tdma_reg &= ~(1UL << DMA_EN); - write32(MAC_REG_BASE_ADDR + TDMA_REG_BASE + DMA_CTRL, tdma_reg); - rdma_reg = read32(MAC_REG_BASE_ADDR + RDMA_REG_BASE + DMA_CTRL); + write32(mac_reg_base_addr + TDMA_REG_BASE + DMA_CTRL, tdma_reg); + rdma_reg = read32(mac_reg_base_addr + RDMA_REG_BASE + DMA_CTRL); rdma_reg &= ~(1UL << DMA_EN); - write32(MAC_REG_BASE_ADDR + RDMA_REG_BASE + DMA_CTRL, rdma_reg); - write32(MAC_REG_BASE_ADDR + UMAC_TX_FLUSH, 1); + write32(mac_reg_base_addr + RDMA_REG_BASE + DMA_CTRL, rdma_reg); + write32(mac_reg_base_addr + UMAC_TX_FLUSH, 1); DELAY_MICROS(100); - write32(MAC_REG_BASE_ADDR + UMAC_TX_FLUSH, 0); + write32(mac_reg_base_addr + UMAC_TX_FLUSH, 0); } static void bcmgenet_enable_dma(void) @@ -176,31 +162,27 @@ static void bcmgenet_enable_dma(void) rt_uint32_t dma_ctrl = 0; dma_ctrl = (1 << (DEFAULT_Q + DMA_RING_BUF_EN_SHIFT)) | DMA_EN; - write32(MAC_REG_BASE_ADDR + TDMA_REG_BASE + DMA_CTRL, dma_ctrl); + write32(mac_reg_base_addr + TDMA_REG_BASE + DMA_CTRL, dma_ctrl); - reg = read32(MAC_REG_BASE_ADDR + RDMA_REG_BASE + DMA_CTRL); - write32(MAC_REG_BASE_ADDR + RDMA_REG_BASE + DMA_CTRL, dma_ctrl | reg); + reg = read32(mac_reg_base_addr + RDMA_REG_BASE + DMA_CTRL); + write32(mac_reg_base_addr + RDMA_REG_BASE + DMA_CTRL, dma_ctrl | reg); } static int bcmgenet_mdio_write(rt_uint32_t addr, rt_uint32_t reg, rt_uint32_t value) { int count = 10000; rt_uint32_t val; - rt_uint32_t reg_val; - val = MDIO_WR | (addr << MDIO_PMD_SHIFT) | (reg << MDIO_REG_SHIFT) | (0xffff & value); - write32(MAC_REG_BASE_ADDR + MDIO_CMD, val); + write32(mac_reg_base_addr + MDIO_CMD, val); - reg_val = read32(MAC_REG_BASE_ADDR + MDIO_CMD); + rt_uint32_t reg_val = read32(mac_reg_base_addr + MDIO_CMD); reg_val = reg_val | MDIO_START_BUSY; - write32(MAC_REG_BASE_ADDR + MDIO_CMD, reg_val); + write32(mac_reg_base_addr + MDIO_CMD, reg_val); - while ((read32(MAC_REG_BASE_ADDR + MDIO_CMD) & MDIO_START_BUSY) && (--count)) - { + while ((read32(mac_reg_base_addr + MDIO_CMD) & MDIO_START_BUSY) && (--count)) DELAY_MICROS(1); - } - reg_val = read32(MAC_REG_BASE_ADDR + MDIO_CMD); + reg_val = read32(mac_reg_base_addr + MDIO_CMD); return reg_val & 0xffff; } @@ -212,18 +194,16 @@ static int bcmgenet_mdio_read(rt_uint32_t addr, rt_uint32_t reg) rt_uint32_t reg_val = 0; val = MDIO_RD | (addr << MDIO_PMD_SHIFT) | (reg << MDIO_REG_SHIFT); - write32(MAC_REG_BASE_ADDR + MDIO_CMD, val); + write32(mac_reg_base_addr + MDIO_CMD, val); - reg_val = read32(MAC_REG_BASE_ADDR + MDIO_CMD); + reg_val = read32(mac_reg_base_addr + MDIO_CMD); reg_val = reg_val | MDIO_START_BUSY; - write32(MAC_REG_BASE_ADDR + MDIO_CMD, reg_val); + write32(mac_reg_base_addr + MDIO_CMD, reg_val); - while ((read32(MAC_REG_BASE_ADDR + MDIO_CMD) & MDIO_START_BUSY) && (--count)) - { + while ((read32(mac_reg_base_addr + MDIO_CMD) & MDIO_START_BUSY) && (--count)) DELAY_MICROS(1); - } - reg_val = read32(MAC_REG_BASE_ADDR + MDIO_CMD); + reg_val = read32(mac_reg_base_addr + MDIO_CMD); return reg_val & 0xffff; } @@ -232,15 +212,13 @@ static int bcmgenet_gmac_write_hwaddr(void) { rt_uint8_t addr[6]; rt_uint32_t reg; - bcm271x_mbox_hardware_get_mac_address(&addr[0]); reg = addr[0] << 24 | addr[1] << 16 | addr[2] << 8 | addr[3]; - write32(MAC_REG_BASE_ADDR + UMAC_MAC0, reg); + write32(mac_reg_base_addr + UMAC_MAC0, reg); reg = addr[4] << 8 | addr[5]; - write32(MAC_REG_BASE_ADDR + UMAC_MAC1, reg); - + write32(mac_reg_base_addr + UMAC_MAC1, reg); return 0; } @@ -258,17 +236,15 @@ static int get_ethernet_uid(void) { LOG_I("version is B1\n"); } - return uid; } static void bcmgenet_mdio_init(void) { - /* get ethernet uid */ - if (get_ethernet_uid() == 0) - { - return; - } + rt_uint32_t ret = 0; + /*get ethernet uid*/ + ret = get_ethernet_uid(); + if (ret == 0) return; /* reset phy */ bcmgenet_mdio_write(1, BCM54213PE_MII_CONTROL, MII_CONTROL_PHY_RESET); @@ -296,34 +272,34 @@ static void bcmgenet_mdio_init(void) static void rx_ring_init(void) { - write32(MAC_REG_BASE_ADDR + RDMA_REG_BASE + DMA_SCB_BURST_SIZE, DMA_MAX_BURST_LENGTH); - write32(MAC_REG_BASE_ADDR + RDMA_RING_REG_BASE + DMA_START_ADDR, 0x0); - write32(MAC_REG_BASE_ADDR + RDMA_READ_PTR, 0x0); - write32(MAC_REG_BASE_ADDR + RDMA_WRITE_PTR, 0x0); - write32(MAC_REG_BASE_ADDR + RDMA_RING_REG_BASE + DMA_END_ADDR, RX_DESCS * DMA_DESC_SIZE / 4 - 1); + write32(mac_reg_base_addr + RDMA_REG_BASE + DMA_SCB_BURST_SIZE, DMA_MAX_BURST_LENGTH); + write32(mac_reg_base_addr + RDMA_RING_REG_BASE + DMA_START_ADDR, 0x0); + write32(mac_reg_base_addr + RDMA_READ_PTR, 0x0); + write32(mac_reg_base_addr + RDMA_WRITE_PTR, 0x0); + write32(mac_reg_base_addr + RDMA_RING_REG_BASE + DMA_END_ADDR, RX_DESCS * DMA_DESC_SIZE / 4 - 1); - write32(MAC_REG_BASE_ADDR + RDMA_PROD_INDEX, 0x0); - write32(MAC_REG_BASE_ADDR + RDMA_CONS_INDEX, 0x0); - write32(MAC_REG_BASE_ADDR + RDMA_RING_REG_BASE + DMA_RING_BUF_SIZE, (RX_DESCS << DMA_RING_SIZE_SHIFT) | RX_BUF_LENGTH); - write32(MAC_REG_BASE_ADDR + RDMA_XON_XOFF_THRESH, DMA_FC_THRESH_VALUE); - write32(MAC_REG_BASE_ADDR + RDMA_REG_BASE + DMA_RING_CFG, 1 << DEFAULT_Q); + write32(mac_reg_base_addr + RDMA_PROD_INDEX, 0x0); + write32(mac_reg_base_addr + RDMA_CONS_INDEX, 0x0); + write32(mac_reg_base_addr + RDMA_RING_REG_BASE + DMA_RING_BUF_SIZE, (RX_DESCS << DMA_RING_SIZE_SHIFT) | RX_BUF_LENGTH); + write32(mac_reg_base_addr + RDMA_XON_XOFF_THRESH, DMA_FC_THRESH_VALUE); + write32(mac_reg_base_addr + RDMA_REG_BASE + DMA_RING_CFG, 1 << DEFAULT_Q); } static void tx_ring_init(void) { - write32(MAC_REG_BASE_ADDR + TDMA_REG_BASE + DMA_SCB_BURST_SIZE, DMA_MAX_BURST_LENGTH); - write32(MAC_REG_BASE_ADDR + TDMA_RING_REG_BASE + DMA_START_ADDR, 0x0); - write32(MAC_REG_BASE_ADDR + TDMA_READ_PTR, 0x0); - write32(MAC_REG_BASE_ADDR + TDMA_READ_PTR, 0x0); - write32(MAC_REG_BASE_ADDR + TDMA_READ_PTR, 0x0); - write32(MAC_REG_BASE_ADDR + TDMA_WRITE_PTR, 0x0); - write32(MAC_REG_BASE_ADDR + TDMA_RING_REG_BASE + DMA_END_ADDR, TX_DESCS * DMA_DESC_SIZE / 4 - 1); - write32(MAC_REG_BASE_ADDR + TDMA_PROD_INDEX, 0x0); - write32(MAC_REG_BASE_ADDR + TDMA_CONS_INDEX, 0x0); - write32(MAC_REG_BASE_ADDR + TDMA_RING_REG_BASE + DMA_MBUF_DONE_THRESH, 0x1); - write32(MAC_REG_BASE_ADDR + TDMA_FLOW_PERIOD, 0x0); - write32(MAC_REG_BASE_ADDR + TDMA_RING_REG_BASE + DMA_RING_BUF_SIZE, (TX_DESCS << DMA_RING_SIZE_SHIFT) | RX_BUF_LENGTH); - write32(MAC_REG_BASE_ADDR + TDMA_REG_BASE + DMA_RING_CFG, 1 << DEFAULT_Q); + write32(mac_reg_base_addr + TDMA_REG_BASE + DMA_SCB_BURST_SIZE, DMA_MAX_BURST_LENGTH); + write32(mac_reg_base_addr + TDMA_RING_REG_BASE + DMA_START_ADDR, 0x0); + write32(mac_reg_base_addr + TDMA_READ_PTR, 0x0); + write32(mac_reg_base_addr + TDMA_READ_PTR, 0x0); + write32(mac_reg_base_addr + TDMA_READ_PTR, 0x0); + write32(mac_reg_base_addr + TDMA_WRITE_PTR, 0x0); + write32(mac_reg_base_addr + TDMA_RING_REG_BASE + DMA_END_ADDR, TX_DESCS * DMA_DESC_SIZE / 4 - 1); + write32(mac_reg_base_addr + TDMA_PROD_INDEX, 0x0); + write32(mac_reg_base_addr + TDMA_CONS_INDEX, 0x0); + write32(mac_reg_base_addr + TDMA_RING_REG_BASE + DMA_MBUF_DONE_THRESH, 0x1); + write32(mac_reg_base_addr + TDMA_FLOW_PERIOD, 0x0); + write32(mac_reg_base_addr + TDMA_RING_REG_BASE + DMA_RING_BUF_SIZE, (TX_DESCS << DMA_RING_SIZE_SHIFT) | RX_BUF_LENGTH); + write32(mac_reg_base_addr + TDMA_REG_BASE + DMA_RING_CFG, 1 << DEFAULT_Q); } static void rx_descs_init(void) @@ -345,7 +321,6 @@ static int bcmgenet_adjust_link(void) { rt_uint32_t speed; rt_uint32_t phy_dev_speed = link_speed; - rt_uint32_t reg1; switch (phy_dev_speed) { @@ -363,12 +338,14 @@ static int bcmgenet_adjust_link(void) return -1; } - reg1 = read32(MAC_REG_BASE_ADDR + EXT_RGMII_OOB_CTRL); - reg1 |= (RGMII_LINK | RGMII_MODE_EN | ID_MODE_DIS); - write32(MAC_REG_BASE_ADDR + EXT_RGMII_OOB_CTRL, reg1); - DELAY_MICROS(1000); - write32(MAC_REG_BASE_ADDR + UMAC_CMD, speed << CMD_SPEED_SHIFT); + rt_uint32_t reg1 = read32(mac_reg_base_addr + EXT_RGMII_OOB_CTRL); + //reg1 &= ~(1UL << OOB_DISABLE); + //rt_kprintf("OOB_DISABLE is %d\n", OOB_DISABLE); + reg1 |= (RGMII_LINK | RGMII_MODE_EN | ID_MODE_DIS); + write32(mac_reg_base_addr + EXT_RGMII_OOB_CTRL, reg1); + DELAY_MICROS(1000); + write32(mac_reg_base_addr + UMAC_CMD, speed << CMD_SPEED_SHIFT); return 0; } @@ -388,49 +365,46 @@ static int bcmgenet_gmac_eth_start(void) bcmgenet_umac_reset(); bcmgenet_gmac_write_hwaddr(); - /* disable RX/TX DMA and flush TX queues */ + /* Disable RX/TX DMA and flush TX queues */ bcmgenet_disable_dma(); rx_ring_init(); rx_descs_init(); tx_ring_init(); - /* enable RX/TX DMA */ + /* Enable RX/TX DMA */ bcmgenet_enable_dma(); - /* ppdate MAC registers based on PHY property */ + /* Update MAC registers based on PHY property */ ret = bcmgenet_adjust_link(); - if (ret) + if(ret) { rt_kprintf("bcmgenet: adjust PHY link failed: %d\n", ret); return ret; } /* wait tx index clear */ - while ((read32(MAC_REG_BASE_ADDR + TDMA_CONS_INDEX) != 0) && (--count)) - { + while ((read32(mac_reg_base_addr + TDMA_CONS_INDEX) != 0) && (--count)) DELAY_MICROS(1); - } - tx_index = read32(MAC_REG_BASE_ADDR + TDMA_CONS_INDEX); - write32(MAC_REG_BASE_ADDR + TDMA_PROD_INDEX, tx_index); + tx_index = read32(mac_reg_base_addr + TDMA_CONS_INDEX); + write32(mac_reg_base_addr + TDMA_PROD_INDEX, tx_index); - index_flag = read32(MAC_REG_BASE_ADDR + RDMA_PROD_INDEX); + index_flag = read32(mac_reg_base_addr + RDMA_PROD_INDEX); - rx_index = index_flag % RX_DESCS; + rx_index = index_flag % 256; - write32(MAC_REG_BASE_ADDR + RDMA_CONS_INDEX, index_flag); - write32(MAC_REG_BASE_ADDR + RDMA_PROD_INDEX, index_flag); + write32(mac_reg_base_addr + RDMA_CONS_INDEX, index_flag); + write32(mac_reg_base_addr + RDMA_PROD_INDEX, index_flag); - /* enable Rx/Tx */ + /* Enable Rx/Tx */ rt_uint32_t rx_tx_en; - rx_tx_en = read32(MAC_REG_BASE_ADDR + UMAC_CMD); + rx_tx_en = read32(mac_reg_base_addr + UMAC_CMD); rx_tx_en |= (CMD_TX_EN | CMD_RX_EN); - write32(MAC_REG_BASE_ADDR + UMAC_CMD, rx_tx_en); - - /* eanble IRQ for TxDMA done and RxDMA done */ - write32(MAC_REG_BASE_ADDR + GENET_INTRL2_CPU_CLEAR_MASK, GENET_IRQ_TXDMA_DONE | GENET_IRQ_RXDMA_DONE); + write32(mac_reg_base_addr + UMAC_CMD, rx_tx_en); + // eanble IRQ for TxDMA done and RxDMA done + write32(mac_reg_base_addr + GENET_INTRL2_CPU_CLEAR_MASK, GENET_IRQ_TXDMA_DONE | GENET_IRQ_RXDMA_DONE); return 0; } @@ -438,22 +412,21 @@ static rt_uint32_t prev_recv_cnt = 0; static rt_uint32_t cur_recv_cnt = 0; static rt_uint32_t bcmgenet_gmac_eth_recv(rt_uint8_t **packetp) { - void *desc_base; - rt_uint32_t length = 0, addr = 0; - rt_uint32_t prod_index = read32(MAC_REG_BASE_ADDR + RDMA_PROD_INDEX); - - /* no buff */ - if (prod_index == index_flag) + void* desc_base; + rt_uint32_t length = 0; + size_t addr = 0; + rt_uint32_t prod_index = read32(mac_reg_base_addr + RDMA_PROD_INDEX); + //get next + if(prod_index == index_flag) { cur_recv_cnt = index_flag; index_flag = 0x7fffffff; - + //no buff return 0; } else { - /* no new buff */ - if (prev_recv_cnt == (prod_index & 0xffff)) + if(prev_recv_cnt == (prod_index & 0xffffUL)) { return 0; } @@ -462,70 +435,74 @@ static rt_uint32_t bcmgenet_gmac_eth_recv(rt_uint8_t **packetp) length = read32(desc_base + DMA_DESC_LENGTH_STATUS); length = (length >> DMA_BUFLENGTH_SHIFT) & DMA_BUFLENGTH_MASK; addr = read32(desc_base + DMA_DESC_ADDRESS_LO); - /* - * to cater for the IP headepr alignment the hardware does. - * This would actually not be needed if we don't program - * RBUF_ALIGN_2B - */ - - /* convert to memory address */ - addr = addr + RECV_DATA_NO_CACHE - RECV_DATA_NO_CACHE; - rt_hw_dcache_invalidate_range(addr, length); - - *packetp = (rt_uint8_t *)(unsigned long)(addr + RX_BUF_OFFSET); + /* To cater for the IP headepr alignment the hardware does. + * This would actually not be needed if we don't program + * RBUF_ALIGN_2B + */ + *packetp = (rt_uint8_t *)(addr + RX_BUF_OFFSET); rx_index = rx_index + 1; - if (rx_index >= RX_DESCS) + if(rx_index >= 256) { rx_index = 0; } - - write32(MAC_REG_BASE_ADDR + RDMA_CONS_INDEX, cur_recv_cnt); + write32(mac_reg_base_addr + RDMA_CONS_INDEX, cur_recv_cnt); cur_recv_cnt = cur_recv_cnt + 1; - if (cur_recv_cnt > 0xffff) + if(cur_recv_cnt > 0xffff) { cur_recv_cnt = 0; } prev_recv_cnt = cur_recv_cnt; - return length - RX_BUF_OFFSET; + return length; } } - -static int bcmgenet_gmac_eth_send(rt_uint32_t packet, int length, struct pbuf *p) +static int bcmgenet_gmac_eth_send(void *packet, int length) { + rt_ubase_t level; void *desc_base = (TX_DESC_BASE + tx_index * DMA_DESC_SIZE); - pbuf_copy_partial(p, (void *)(unsigned long)(packet + tx_index * SEND_CACHE_BUF), p->tot_len, 0); rt_uint32_t len_stat = length << DMA_BUFLENGTH_SHIFT; + + rt_uint32_t prod_index, cons; + rt_uint32_t tries = 100; + + prod_index = read32(mac_reg_base_addr + TDMA_PROD_INDEX); + len_stat |= 0x3F << DMA_TX_QTAG_SHIFT; len_stat |= DMA_TX_APPEND_CRC | DMA_SOP | DMA_EOP; - rt_hw_dcache_flush_range(packet + tx_index * SEND_CACHE_BUF, length); - rt_uint32_t prod_index; - - prod_index = read32(MAC_REG_BASE_ADDR + TDMA_PROD_INDEX); - - write32((desc_base + DMA_DESC_ADDRESS_LO), SEND_DATA_NO_CACHE + tx_index * SEND_CACHE_BUF); + write32((desc_base + DMA_DESC_ADDRESS_LO), SEND_DATA_NO_CACHE); write32((desc_base + DMA_DESC_ADDRESS_HI), 0); write32((desc_base + DMA_DESC_LENGTH_STATUS), len_stat); - tx_index++; - if (tx_index >= TX_DESCS) - { - tx_index = 0; - } + tx_index = tx_index == 255? 0 : tx_index + 1; prod_index = prod_index + 1; - if (prod_index > 0xffff) + if (prod_index == 0xe000) { + write32(mac_reg_base_addr + TDMA_PROD_INDEX, 0); prod_index = 0; } - /* start Transmisson */ - write32(MAC_REG_BASE_ADDR + TDMA_PROD_INDEX, prod_index); + /* Start Transmisson */ + write32(mac_reg_base_addr + TDMA_PROD_INDEX, prod_index); + + level = rt_hw_interrupt_disable(); + do + { + cons = read32(mac_reg_base_addr + TDMA_CONS_INDEX); + } while ((cons & 0xffff) < prod_index && --tries); + rt_hw_interrupt_enable(level); + + if (!tries) + { + rt_kprintf("send err! tries is %d\n", tries); + return -1; + } + return 0; } @@ -535,10 +512,10 @@ static void link_task_entry(void *param) RT_ASSERT(eth_device != RT_NULL); struct rt_eth_dev *dev = ð_dev; - /* start mdio */ + //start mdio bcmgenet_mdio_init(); - /* start timer link */ + //start timer link rt_timer_init(&dev->link_timer, "link_timer", link_irq, NULL, @@ -546,16 +523,16 @@ static void link_task_entry(void *param) RT_TIMER_FLAG_PERIODIC); rt_timer_start(&dev->link_timer); - /* link wait forever */ + //link wait forever rt_sem_take(&link_ack, RT_WAITING_FOREVER); - /* link up */ - eth_device_linkchange(ð_dev.parent, RT_TRUE); + eth_device_linkchange(ð_dev.parent, RT_TRUE); //link up rt_timer_stop(&dev->link_timer); - /* set mac */ + //set mac + // bcmgenet_gmac_write_hwaddr(); bcmgenet_gmac_write_hwaddr(); - /* check link speed */ + //check link speed if ((bcmgenet_mdio_read(1, BCM54213PE_STATUS) & (1 << 10)) || (bcmgenet_mdio_read(1, BCM54213PE_STATUS) & (1 << 11))) { link_speed = 1000; @@ -572,7 +549,6 @@ static void link_task_entry(void *param) rt_kprintf("Support link mode Speed 10M\n"); } - /* convert to memory address */ bcmgenet_gmac_eth_start(); rt_hw_interrupt_install(ETH_IRQ, eth_rx_irq, NULL, "eth_irq"); @@ -586,27 +562,20 @@ static rt_err_t bcmgenet_eth_init(rt_device_t device) rt_uint32_t ret = 0; rt_uint32_t hw_reg = 0; - /* read GENET HW version */ + /* Read GENET HW version */ rt_uint8_t major = 0; - hw_reg = read32(MAC_REG_BASE_ADDR + SYS_REV_CTRL); + hw_reg = read32(mac_reg_base_addr + SYS_REV_CTRL); major = (hw_reg >> 24) & 0x0f; - if (major != 6) { if (major == 5) - { major = 4; - } else if (major == 0) - { major = 1; - } rt_kprintf("Uns upported GENETv%d.%d\n", major, (hw_reg >> 16) & 0x0f); - - return -RT_ERROR; + return RT_ERROR; } - /* set interface */ ret = bcmgenet_interface_set(); if (ret) @@ -615,20 +584,18 @@ static rt_err_t bcmgenet_eth_init(rt_device_t device) } /* rbuf clear */ - write32(MAC_REG_BASE_ADDR + SYS_RBUF_FLUSH_CTRL, 0); + write32(mac_reg_base_addr + SYS_RBUF_FLUSH_CTRL, 0); /* disable MAC while updating its registers */ - write32(MAC_REG_BASE_ADDR + UMAC_CMD, 0); + write32(mac_reg_base_addr + UMAC_CMD, 0); /* issue soft reset with (rg)mii loopback to ensure a stable rxclk */ - write32(MAC_REG_BASE_ADDR + UMAC_CMD, CMD_SW_RESET | CMD_LCL_LOOP_EN); + write32(mac_reg_base_addr + UMAC_CMD, CMD_SW_RESET | CMD_LCL_LOOP_EN); link_thread_tid = rt_thread_create("link", link_task_entry, (void *)device, LINK_THREAD_STACK_SIZE, LINK_THREAD_PRIORITY, LINK_THREAD_TIMESLICE); if (link_thread_tid != RT_NULL) - { rt_thread_startup(link_thread_tid); - } return RT_EOK; } @@ -639,13 +606,9 @@ static rt_err_t bcmgenet_eth_control(rt_device_t dev, int cmd, void *args) { case NIOCTL_GADDR: if (args) - { rt_memcpy(args, eth_dev.dev_addr, 6); - } else - { return -RT_ERROR; - } break; default: break; @@ -655,31 +618,46 @@ static rt_err_t bcmgenet_eth_control(rt_device_t dev, int cmd, void *args) rt_err_t rt_eth_tx(rt_device_t device, struct pbuf *p) { - if (link_flag == 1) + int copy_len = 0; + + /* lock eth device */ + if (link_flag != 1) { - bcmgenet_gmac_eth_send((rt_uint32_t)SEND_DATA_NO_CACHE, p->tot_len, p); - rt_sem_take(&send_finsh_sem_lock, RT_WAITING_FOREVER); + rt_kprintf("link disconnected\n"); + return -RT_ERROR; } + copy_len = pbuf_copy_partial(p, eth_send_no_cache, p->tot_len, 0); + if (copy_len == 0) + { + + rt_kprintf("copy len is zero\n"); + return -RT_ERROR; + } + bcmgenet_gmac_eth_send((void *)eth_send_no_cache, p->tot_len); + return RT_EOK; } struct pbuf *rt_eth_rx(rt_device_t device) { int recv_len = 0; - rt_uint8_t *addr_point = RT_NULL; + size_t addr_point; struct pbuf *pbuf = RT_NULL; - - if (link_flag == 1) + if (link_flag != 1) { - recv_len = bcmgenet_gmac_eth_recv(&addr_point); - if (recv_len > 0) + return RT_NULL; + } + + recv_len = bcmgenet_gmac_eth_recv((rt_uint8_t **)&addr_point); + if (recv_len > 0) + { + pbuf = pbuf_alloc(PBUF_LINK, ENET_FRAME_MAX_FRAMELEN, PBUF_POOL); + if (pbuf != RT_NULL) { - pbuf = pbuf_alloc(PBUF_LINK, recv_len, PBUF_RAM); - if (pbuf) - { - rt_memcpy(pbuf->payload, addr_point, recv_len); - } + //calc offset + addr_point= (size_t)(addr_point+ (eth_recv_no_cache - RECV_DATA_NO_CACHE)); + rt_memcpy(pbuf->payload, (char *)addr_point, recv_len); } } @@ -689,14 +667,15 @@ struct pbuf *rt_eth_rx(rt_device_t device) int rt_hw_eth_init(void) { rt_uint8_t mac_addr[6]; - rt_sem_init(&send_finsh_sem_lock, "send_finsh_sem_lock", TX_DESCS, RT_IPC_FLAG_FIFO); + rt_sem_init(&link_ack, "link_ack", 0, RT_IPC_FLAG_FIFO); + memset(ð_dev, 0, sizeof(eth_dev)); - memset((void *)SEND_DATA_NO_CACHE, 0, DMA_DISC_ADDR_SIZE); - memset((void *)RECV_DATA_NO_CACHE, 0, DMA_DISC_ADDR_SIZE); + memset((void *)eth_send_no_cache, 0, sizeof(DMA_DISC_ADDR_SIZE)); + memset((void *)eth_recv_no_cache, 0, sizeof(DMA_DISC_ADDR_SIZE)); bcm271x_mbox_hardware_get_mac_address(&mac_addr[0]); - eth_dev.iobase = MAC_REG_BASE_ADDR; + eth_dev.iobase = mac_reg_base_addr; eth_dev.name = "e0"; eth_dev.dev_addr[0] = mac_addr[0]; eth_dev.dev_addr[1] = mac_addr[1]; @@ -705,24 +684,20 @@ int rt_hw_eth_init(void) eth_dev.dev_addr[4] = mac_addr[4]; eth_dev.dev_addr[5] = mac_addr[5]; - eth_dev.parent.parent.type = RT_Device_Class_NetIf; - eth_dev.parent.parent.init = bcmgenet_eth_init; - eth_dev.parent.parent.open = RT_NULL; - eth_dev.parent.parent.close = RT_NULL; - eth_dev.parent.parent.read = RT_NULL; - eth_dev.parent.parent.write = RT_NULL; - eth_dev.parent.parent.control = bcmgenet_eth_control; - eth_dev.parent.parent.user_data = RT_NULL; + eth_dev.parent.parent.type = RT_Device_Class_NetIf; + eth_dev.parent.parent.init = bcmgenet_eth_init; + eth_dev.parent.parent.open = RT_NULL; + eth_dev.parent.parent.close = RT_NULL; + eth_dev.parent.parent.read = RT_NULL; + eth_dev.parent.parent.write = RT_NULL; + eth_dev.parent.parent.control = bcmgenet_eth_control; + eth_dev.parent.parent.user_data = RT_NULL; eth_dev.parent.eth_tx = rt_eth_tx; eth_dev.parent.eth_rx = rt_eth_rx; eth_device_init(&(eth_dev.parent), "e0"); - /* link down */ - eth_device_linkchange(ð_dev.parent, RT_FALSE); - + eth_device_linkchange(ð_dev.parent, RT_FALSE); //link down return 0; } INIT_COMPONENT_EXPORT(rt_hw_eth_init); - -#endif /* BSP_USING_ETH */ diff --git a/bsp/raspberry-pi/raspi4-64/drivers/drv_eth.h b/bsp/raspberry-pi/raspi4-64/drivers/drv_eth.h new file mode 100644 index 0000000000..952c8c5bc1 --- /dev/null +++ b/bsp/raspberry-pi/raspi4-64/drivers/drv_eth.h @@ -0,0 +1,225 @@ + +/* + * Copyright (c) 2006-2020, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2020-10-30 bigmagic first version + */ + +#ifndef __DRV_ETH_H__ +#define __DRV_ETH_H__ + + +//#define BIT(nr) (1UL << (nr)) +#define ENET_FRAME_MAX_FRAMELEN 1518U + +#define SYS_REV_CTRL (0x00) +#define SYS_PORT_CTRL (0x04) +#define PORT_MODE_EXT_GPHY (3) + +#define GENET_SYS_OFF (0x0000) +#define SYS_RBUF_FLUSH_CTRL (GENET_SYS_OFF + 0x08) +#define SYS_TBUF_FLUSH_CTRL (GENET_SYS_OFF + 0x0c) + +#define GENET_EXT_OFF (0x0080) +#define EXT_RGMII_OOB_CTRL (GENET_EXT_OFF + 0x0c) +#define RGMII_LINK BIT(4) +#define OOB_DISABLE BIT(5) +#define RGMII_MODE_EN BIT(6) +#define ID_MODE_DIS BIT(16) + +#define GENET_RBUF_OFF (0x0300) +#define RBUF_TBUF_SIZE_CTRL (GENET_RBUF_OFF + 0xb4) +#define RBUF_CTRL (GENET_RBUF_OFF + 0x00) +#define RBUF_ALIGN_2B BIT(1) + +#define GENET_UMAC_OFF (0x0800) +#define UMAC_MIB_CTRL (GENET_UMAC_OFF + 0x580) +#define UMAC_MAX_FRAME_LEN (GENET_UMAC_OFF + 0x014) +#define UMAC_MAC0 (GENET_UMAC_OFF + 0x00c) +#define UMAC_MAC1 (GENET_UMAC_OFF + 0x010) +#define UMAC_CMD (GENET_UMAC_OFF + 0x008) +#define MDIO_CMD (GENET_UMAC_OFF + 0x614) +#define UMAC_TX_FLUSH (GENET_UMAC_OFF + 0x334) +#define MDIO_START_BUSY BIT(29) +#define MDIO_READ_FAIL BIT(28) +#define MDIO_RD (2 << 26) +#define MDIO_WR BIT(26) +#define MDIO_PMD_SHIFT (21) +#define MDIO_PMD_MASK (0x1f) +#define MDIO_REG_SHIFT (16) +#define MDIO_REG_MASK (0x1f) + +#define GENET_INTRL2_OFF (0x0200) +#define GENET_INTRL2_CPU_STAT (GENET_INTRL2_OFF + 0x00) +#define GENET_INTRL2_CPU_CLEAR (GENET_INTRL2_OFF + 0x08) +#define GENET_INTRL2_CPU_STAT_MASK (GENET_INTRL2_OFF + 0x0c) +#define GENET_INTRL2_CPU_SET_MASK (GENET_INTRL2_OFF + 0x10) +#define GENET_INTRL2_CPU_CLEAR_MASK (GENET_INTRL2_OFF + 0x14) +#define GENET_IRQ_MDIO_ERROR BIT(24) +#define GENET_IRQ_MDIO_DONE BIT(23) +#define GENET_IRQ_TXDMA_DONE BIT(16) +#define GENET_IRQ_RXDMA_DONE BIT(13) + +#define CMD_TX_EN BIT(0) +#define CMD_RX_EN BIT(1) +#define UMAC_SPEED_10 (0) +#define UMAC_SPEED_100 (1) +#define UMAC_SPEED_1000 (2) +#define UMAC_SPEED_2500 (3) +#define CMD_SPEED_SHIFT (2) +#define CMD_SPEED_MASK (3) +#define CMD_SW_RESET BIT(13) +#define CMD_LCL_LOOP_EN BIT(15) +#define CMD_TX_EN BIT(0) +#define CMD_RX_EN BIT(1) + +#define MIB_RESET_RX BIT(0) +#define MIB_RESET_RUNT BIT(1) +#define MIB_RESET_TX BIT(2) + +/* total number of Buffer Descriptors, same for Rx/Tx */ +#define TOTAL_DESCS (256) +#define RX_DESCS TOTAL_DESCS +#define TX_DESCS TOTAL_DESCS + +#define DEFAULT_Q (0x10) + +#define ETH_DATA_LEN (1500) +#define ETH_HLEN (14) +#define VLAN_HLEN (4) +#define ETH_FCS_LEN (4) +/* Body(1500) + EH_SIZE(14) + VLANTAG(4) + BRCMTAG(6) + FCS(4) = 1528. + * 1536 is multiple of 256 bytes + */ +#define ENET_BRCM_TAG_LEN (6) +#define ENET_PAD (8) +#define ENET_MAX_MTU_SIZE (ETH_DATA_LEN + ETH_HLEN + \ + VLAN_HLEN + ENET_BRCM_TAG_LEN + \ + ETH_FCS_LEN + ENET_PAD) + +/* Tx/Rx Dma Descriptor common bits */ +#define DMA_EN BIT(0) +#define DMA_RING_BUF_EN_SHIFT (0x01) +#define DMA_RING_BUF_EN_MASK (0xffff) +#define DMA_BUFLENGTH_MASK (0x0fff) +#define DMA_BUFLENGTH_SHIFT (16) +#define DMA_RING_SIZE_SHIFT (16) +#define DMA_OWN (0x8000) +#define DMA_EOP (0x4000) +#define DMA_SOP (0x2000) +#define DMA_WRAP (0x1000) +#define DMA_MAX_BURST_LENGTH (0x8) +/* Tx specific DMA descriptor bits */ +#define DMA_TX_UNDERRUN (0x0200) +#define DMA_TX_APPEND_CRC (0x0040) +#define DMA_TX_OW_CRC (0x0020) +#define DMA_TX_DO_CSUM (0x0010) +#define DMA_TX_QTAG_SHIFT (7) + +/* DMA rings size */ +#define DMA_RING_SIZE (0x40) +#define DMA_RINGS_SIZE (DMA_RING_SIZE * (DEFAULT_Q + 1)) + +/* DMA descriptor */ +#define DMA_DESC_LENGTH_STATUS (0x00) +#define DMA_DESC_ADDRESS_LO (0x04) +#define DMA_DESC_ADDRESS_HI (0x08) +#define DMA_DESC_SIZE (12) + +#define GENET_RX_OFF (0x2000) +#define GENET_RDMA_REG_OFF \ + (GENET_RX_OFF + TOTAL_DESCS * DMA_DESC_SIZE) +#define GENET_TX_OFF (0x4000) +#define GENET_TDMA_REG_OFF \ + (GENET_TX_OFF + TOTAL_DESCS * DMA_DESC_SIZE) + +#define DMA_FC_THRESH_HI (RX_DESCS >> 4) +#define DMA_FC_THRESH_LO (5) +#define DMA_FC_THRESH_VALUE ((DMA_FC_THRESH_LO << 16) | \ + DMA_FC_THRESH_HI) + +#define DMA_XOFF_THRESHOLD_SHIFT (16) + +#define TDMA_RING_REG_BASE \ + (GENET_TDMA_REG_OFF + DEFAULT_Q * DMA_RING_SIZE) +#define TDMA_READ_PTR (TDMA_RING_REG_BASE + 0x00) +#define TDMA_CONS_INDEX (TDMA_RING_REG_BASE + 0x08) +#define TDMA_PROD_INDEX (TDMA_RING_REG_BASE + 0x0c) +#define DMA_RING_BUF_SIZE (0x10) +#define DMA_START_ADDR (0x14) +#define DMA_END_ADDR (0x1c) +#define DMA_MBUF_DONE_THRESH (0x24) +#define TDMA_FLOW_PERIOD (TDMA_RING_REG_BASE + 0x28) +#define TDMA_WRITE_PTR (TDMA_RING_REG_BASE + 0x2c) + +#define RDMA_RING_REG_BASE \ + (GENET_RDMA_REG_OFF + DEFAULT_Q * DMA_RING_SIZE) +#define RDMA_WRITE_PTR (RDMA_RING_REG_BASE + 0x00) +#define RDMA_PROD_INDEX (RDMA_RING_REG_BASE + 0x08) +#define RDMA_CONS_INDEX (RDMA_RING_REG_BASE + 0x0c) +#define RDMA_XON_XOFF_THRESH (RDMA_RING_REG_BASE + 0x28) +#define RDMA_READ_PTR (RDMA_RING_REG_BASE + 0x2c) + +#define TDMA_REG_BASE (GENET_TDMA_REG_OFF + DMA_RINGS_SIZE) +#define RDMA_REG_BASE (GENET_RDMA_REG_OFF + DMA_RINGS_SIZE) +#define DMA_RING_CFG (0x00) +#define DMA_CTRL (0x04) +#define DMA_SCB_BURST_SIZE (0x0c) + +#define RX_BUF_LENGTH (2048) +#define RX_TOTAL_BUFSIZE (RX_BUF_LENGTH * RX_DESCS) +#define RX_BUF_OFFSET (2) + +#define PHY_INTERFACE_MODE_RGMII (7) +#define PHY_INTERFACE_MODE_RGMII_RXID (9) + +#define BCM54213PE_MII_CONTROL (0x00) +#define BCM54213PE_MII_STATUS (0x01) +#define BCM54213PE_PHY_IDENTIFIER_HIGH (0x02) +#define BCM54213PE_PHY_IDENTIFIER_LOW (0x03) + +#define BCM54213PE_AUTO_NEGOTIATION_ADV (0x04) +#define BCM54213PE_AUTO_NEGOTIATION_LINK (0x05) +#define BCM54213PE_AUTO_NEGOTIATION_EXPANSION (0x06) + +#define BCM54213PE_NEXT_PAGE_TX (0x07) + +#define BCM54213PE_PARTNER_RX (0x08) + +#define BCM54213PE_CONTROL (0x09) +#define BCM54213PE_STATUS (0x0A) + +#define BCM54213PE_IEEE_EXTENDED_STATUS (0x0F) +#define BCM54213PE_PHY_EXTENDED_CONTROL (0x10) +#define BCM54213PE_PHY_EXTENDED_STATUS (0x11) + +#define BCM54213PE_RECEIVE_ERROR_COUNTER (0x12) +#define BCM54213PE_FALSE_C_S_COUNTER (0x13) +#define BCM54213PE_RECEIVE_NOT_OK_COUNTER (0x14) + +#define BCM54213PE_VERSION_B1 (0x600d84a2) +#define BCM54213PE_VERSION_X (0x600d84a0) + +//BCM54213PE_MII_CONTROL +#define MII_CONTROL_PHY_RESET (1 << 15) +#define MII_CONTROL_AUTO_NEGOTIATION_ENABLED (1 << 12) +#define MII_CONTROL_AUTO_NEGOTIATION_RESTART (1 << 9) +#define MII_CONTROL_PHY_FULL_DUPLEX (1 << 8) +#define MII_CONTROL_SPEED_SELECTION (1 << 6) + +//BCM54213PE_MII_STATUS +#define MII_STATUS_LINK_UP (1 << 2) + +//BCM54213PE_CONTROL +#define CONTROL_FULL_DUPLEX_CAPABILITY (1 << 9) +#define CONTROL_HALF_DUPLEX_CAPABILITY (1 << 8) + +#define SPEED_1000 (1000) +#define SPEED_100 (100) +#define SPEED_10 (10) + +#endif/* __DRV_ETH_H__ */ diff --git a/bsp/raspberry-pi/raspi4-64/drivers/drv_gpio.c b/bsp/raspberry-pi/raspi4-64/drivers/drv_gpio.c new file mode 100644 index 0000000000..ff284e546b --- /dev/null +++ b/bsp/raspberry-pi/raspi4-64/drivers/drv_gpio.c @@ -0,0 +1,439 @@ +/* + * Copyright (c) 2006-2020, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2020-04-16 bigmagic first version + * 2020-06-16 bigmagic add gpio irq + */ + +#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]; + +uint32_t raspi_get_pin_state(uint32_t fselnum) +{ + uint32_t gpfsel = 0; + + switch (fselnum) + { + case 0: + gpfsel = GPIO_REG_GPFSEL0(gpio_base_addr); + break; + case 1: + gpfsel = GPIO_REG_GPFSEL1(gpio_base_addr); + break; + case 2: + gpfsel = GPIO_REG_GPFSEL2(gpio_base_addr); + break; + case 3: + gpfsel = GPIO_REG_GPFSEL3(gpio_base_addr); + break; + case 4: + gpfsel = GPIO_REG_GPFSEL4(gpio_base_addr); + break; + case 5: + gpfsel = GPIO_REG_GPFSEL5(gpio_base_addr); + break; + default: + break; + } + return gpfsel; +} + +void raspi_set_pin_state(uint32_t fselnum, uint32_t gpfsel) +{ + switch (fselnum) + { + case 0: + GPIO_REG_GPFSEL0(gpio_base_addr) = gpfsel; + break; + case 1: + GPIO_REG_GPFSEL1(gpio_base_addr) = gpfsel; + break; + case 2: + GPIO_REG_GPFSEL2(gpio_base_addr) = gpfsel; + break; + case 3: + GPIO_REG_GPFSEL3(gpio_base_addr) = gpfsel; + break; + case 4: + GPIO_REG_GPFSEL4(gpio_base_addr) = gpfsel; + break; + case 5: + GPIO_REG_GPFSEL5(gpio_base_addr) = gpfsel; + break; + default: + break; + } +} + +static void gpio_set_pud(GPIO_PIN pin, GPIO_PUPD_FUNC mode) +{ + uint32_t fselnum = pin / 16; + uint32_t fselrest = pin % 16; + uint32_t reg_value = 0; + + switch (fselnum) + { + case 0: + reg_value = GPIO_PUP_PDN_CNTRL_REG0(gpio_base_addr); + GPIO_PUP_PDN_CNTRL_REG0(gpio_base_addr) = (reg_value | (mode << (fselrest*2))); + break; + case 1: + reg_value = GPIO_PUP_PDN_CNTRL_REG1(gpio_base_addr); + GPIO_PUP_PDN_CNTRL_REG1(gpio_base_addr) = (reg_value | (mode << (fselrest*2))); + break; + + case 2: + reg_value = GPIO_PUP_PDN_CNTRL_REG2(gpio_base_addr); + GPIO_PUP_PDN_CNTRL_REG2(gpio_base_addr) = (reg_value | (mode << (fselrest*2))); + break; + + case 3: + reg_value = GPIO_PUP_PDN_CNTRL_REG3(gpio_base_addr); + GPIO_PUP_PDN_CNTRL_REG3(gpio_base_addr) = (reg_value | (mode << (fselrest*2))); + break; + default: + break; + } +} + +void prev_raspi_pin_mode(GPIO_PIN pin, GPIO_FUNC mode) +{ + uint32_t fselnum = pin / 10; + uint32_t fselrest = pin % 10; + uint32_t gpfsel = 0; + + gpfsel = raspi_get_pin_state(fselnum); + gpfsel &= ~((uint32_t)(0x07 << (fselrest * 3))); + gpfsel |= (uint32_t)(mode << (fselrest * 3)); + raspi_set_pin_state(fselnum, gpfsel); +} + +void prev_raspi_pin_write(GPIO_PIN pin, int pin_value) +{ + uint32_t num = pin / 32; + + if(num == 0) + { + if(pin_value == 1) + { + GPIO_REG_GPSET0(gpio_base_addr) = 1 << (pin % 32); + } + else + { + GPIO_REG_GPCLR0(gpio_base_addr) = 1 << (pin % 32); + } + } + else + { + if(pin_value == 1) + { + GPIO_REG_GPSET1(gpio_base_addr) = 1 << (pin % 32); + } + else + { + GPIO_REG_GPCLR1(gpio_base_addr) = 1 << (pin % 32); + } + } +} + +static void raspi_pin_mode(struct rt_device *dev, rt_base_t pin, rt_uint8_t mode) +{ + GPIO_FUNC raspi_mode = OUTPUT; + + switch (mode) + { + case PIN_MODE_OUTPUT: + raspi_mode = OUTPUT; + break; + case PIN_MODE_INPUT: + raspi_mode = INPUT; + break; + case PIN_MODE_INPUT_PULLUP: + gpio_set_pud(pin, RASPI_PULL_UP); + raspi_mode = INPUT; + break; + case PIN_MODE_INPUT_PULLDOWN: + gpio_set_pud(pin, RASPI_PULL_DOWN); + raspi_mode = INPUT; + break; + case PIN_MODE_OUTPUT_OD: + raspi_mode = OUTPUT; + break; + } + prev_raspi_pin_mode((GPIO_PIN)pin, raspi_mode); +} + +static void raspi_pin_write(struct rt_device *dev, rt_base_t pin, rt_uint8_t value) +{ + prev_raspi_pin_write(pin, value); +} + +static rt_int8_t raspi_pin_read(struct rt_device *device, rt_base_t pin) +{ + uint32_t num = pin / 32; + uint32_t pin_level = 0; + + if(num == 0) + { + if(GPIO_REG_GPLEV0(gpio_base_addr) & (1 << pin)) + { + pin_level = 1; + } + else + { + pin_level = 0; + } + + } + else + { + if(GPIO_REG_GPLEV1(gpio_base_addr) & (1 << pin)) + { + pin_level = 1; + } + else + { + pin_level = 0; + } + } + + return pin_level; +} + +static rt_err_t raspi_pin_attach_irq(struct rt_device *device, rt_base_t pin, rt_uint8_t mode, void (*hdr)(void *args), void *args) +{ + 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_uint8_t pin_num = pin / 32; + rt_uint32_t mask = 1 << shift; + + switch (mode) + { + case PIN_IRQ_MODE_RISING: + if(pin_num == 0) + { + reg_value = GPIO_REG_GPREN0(gpio_base_addr); + GPIO_REG_GPREN0(gpio_base_addr) = (reg_value & ~ mask) | (mask); + } + else + { + reg_value = GPIO_REG_GPREN1(gpio_base_addr); + GPIO_REG_GPREN1(gpio_base_addr) = (reg_value & ~ mask) | (mask); + } + break; + case PIN_IRQ_MODE_FALLING: + if(pin_num == 0) + { + reg_value = GPIO_REG_GPFEN0(gpio_base_addr); + GPIO_REG_GPFEN0(gpio_base_addr) = (reg_value & ~ mask) | (mask); + } + else + { + reg_value = GPIO_REG_GPFEN1(gpio_base_addr); + GPIO_REG_GPFEN1(gpio_base_addr) = (reg_value & ~ mask) | (mask); + } + break; + case PIN_IRQ_MODE_RISING_FALLING: + if(pin_num == 0) + { + reg_value = GPIO_REG_GPAREN0(gpio_base_addr); + GPIO_REG_GPAREN0(gpio_base_addr) = (reg_value & ~ mask) | (mask); + reg_value = GPIO_REG_GPFEN0(gpio_base_addr); + GPIO_REG_GPFEN0(gpio_base_addr) = (reg_value & ~ mask) | (mask); + } + else + { + reg_value = GPIO_REG_GPAREN1(gpio_base_addr); + GPIO_REG_GPAREN1(gpio_base_addr) = (reg_value & ~ mask) | (mask); + reg_value = GPIO_REG_GPFEN1(gpio_base_addr); + GPIO_REG_GPFEN1(gpio_base_addr) = (reg_value & ~ mask) | (mask); + } + break; + case PIN_IRQ_MODE_HIGH_LEVEL: + if(pin_num == 0) + { + reg_value = GPIO_REG_GPHEN0(gpio_base_addr); + GPIO_REG_GPHEN0(gpio_base_addr) = (reg_value & ~ mask) | (mask); + } + else + { + reg_value = GPIO_REG_GPHEN1(gpio_base_addr); + GPIO_REG_GPHEN1(gpio_base_addr) = (reg_value & ~ mask) | ( mask); + } + break; + case PIN_IRQ_MODE_LOW_LEVEL: + if(pin_num == 0) + { + reg_value = GPIO_REG_GPLEN0(gpio_base_addr); + GPIO_REG_GPLEN0(gpio_base_addr) = (reg_value & ~ mask) | (mask); + } + else + { + reg_value = GPIO_REG_GPLEN1(gpio_base_addr); + GPIO_REG_GPLEN1(gpio_base_addr) = (reg_value & ~ mask) | (mask); + } + break; + } + return RT_EOK; +} + +static rt_err_t raspi_pin_detach_irq(struct rt_device *device, rt_base_t pin) +{ + 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] = RT_NULL; + _g_gpio_irq_tbl[index].irq_arg[pin] = RT_NULL; + _g_gpio_irq_tbl[index].irq_type[pin] = RT_NULL; + _g_gpio_irq_tbl[index].state[pin] = RT_NULL; + + return RT_EOK; +} + +rt_err_t raspi_pin_irq_enable(struct rt_device *device, rt_base_t pin, rt_uint8_t enabled) +{ + rt_uint8_t index; + if (pin <= 27) + index = 0; + else if (pin <= 45) + index = 1; + else + index = 2; + + if (enabled) + _g_gpio_irq_tbl[index].state[pin] = 1; + else + _g_gpio_irq_tbl[index].state[pin] = 0; + + return RT_EOK; +} + +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, + RT_NULL, +}; + +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 = GPIO_REG_GPEDS0(gpio_base_addr); + value &= 0x0fffffff; + pin = 0; + GPIO_REG_GPEDS0(gpio_base_addr) = value; + } + else if(irq == IRQ_GPIO1) + { + /* 28-45 */ + tmpvalue = GPIO_REG_GPEDS0(gpio_base_addr); + tmpvalue &= (~0x0fffffff); + GPIO_REG_GPEDS0(gpio_base_addr) = tmpvalue; + + value = GPIO_REG_GPEDS1(gpio_base_addr); + value &= 0x3fff; + GPIO_REG_GPEDS1(gpio_base_addr) = value; + value = (value) | tmpvalue; + pin = 28; + } + else if (irq == IRQ_GPIO2) + { + /* 46-53 */ + value = GPIO_REG_GPEDS1(gpio_base_addr); + value &= (~0x3fff); + GPIO_REG_GPEDS1(gpio_base_addr) = value; + pin = 46; + } + + while (value) + { + if ((value & 0x1) && (irq_def->irq_cb[pin] != RT_NULL)) + { + if(irq_def->state[pin]) + { + irq_def->irq_cb[pin](irq_def->irq_arg[pin]); + } + } + pin++; + value = value >> 1; + } +} +#endif + +int rt_hw_gpio_init(void) +{ +#ifdef BSP_USING_PIN + rt_device_pin_register("gpio", &ops, RT_NULL); + + //disable all intr + GPIO_REG_GPEDS0(gpio_base_addr) = 0xffffffff; + GPIO_REG_GPEDS1(gpio_base_addr) = 0xffffffff; + + GPIO_REG_GPREN0(gpio_base_addr) = 0x0; + GPIO_REG_GPREN1(gpio_base_addr) = 0x0; + + GPIO_REG_GPFEN0(gpio_base_addr) = 0x0; + GPIO_REG_GPFEN1(gpio_base_addr) = 0x0; + + GPIO_REG_GPHEN0(gpio_base_addr) = 0x0; + GPIO_REG_GPHEN1(gpio_base_addr) = 0x0; + + GPIO_REG_GPAREN0(gpio_base_addr) = 0x0; + GPIO_REG_GPAREN1(gpio_base_addr) = 0x0; + + GPIO_REG_GPAFEN0(gpio_base_addr) = 0x0; + GPIO_REG_GPAFEN0(gpio_base_addr) = 0x0; + + 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/raspi4-64/driver/drv_gpio.h b/bsp/raspberry-pi/raspi4-64/drivers/drv_gpio.h similarity index 87% rename from bsp/raspberry-pi/raspi4-64/driver/drv_gpio.h rename to bsp/raspberry-pi/raspi4-64/drivers/drv_gpio.h index 4daa64c2c4..5f564e35d1 100644 --- a/bsp/raspberry-pi/raspi4-64/driver/drv_gpio.h +++ b/bsp/raspberry-pi/raspi4-64/drivers/drv_gpio.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2021, RT-Thread Development Team + * Copyright (c) 2006-2023, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * @@ -17,6 +17,14 @@ #include "board.h" #include "interrupt.h" +struct gpio_irq_def +{ + void *irq_arg[32]; + void (*irq_cb[32])(void *param); + rt_uint8_t irq_type[32]; + rt_uint8_t state[32]; +}; + #define GPIO_REG_GPFSEL0(BASE) HWREG32(BASE + 0x00) #define GPIO_REG_GPFSEL1(BASE) HWREG32(BASE + 0x04) #define GPIO_REG_GPFSEL2(BASE) HWREG32(BASE + 0x08) @@ -59,6 +67,10 @@ #define GPIO_REG_GPPUDCLK1(BASE) HWREG32(BASE + 0x9C) #define GPIO_REG_REV9(BASE) HWREG32(BASE + 0xA0) #define GPIO_REG_TEST(BASE) HWREG32(BASE + 0xA4) +#define GPIO_PUP_PDN_CNTRL_REG0(BASE) HWREG32(BASE + 0xE4) +#define GPIO_PUP_PDN_CNTRL_REG1(BASE) HWREG32(BASE + 0xE8) +#define GPIO_PUP_PDN_CNTRL_REG2(BASE) HWREG32(BASE + 0xEC) +#define GPIO_PUP_PDN_CNTRL_REG3(BASE) HWREG32(BASE + 0xF0) typedef enum { GPIO_PIN_0, @@ -115,6 +127,12 @@ typedef enum { ALT5 = 0b010 } GPIO_FUNC; +typedef enum { + RASPI_NO_RESISTOR = 0x00, + RASPI_PULL_UP = 0x01, + RASPI_PULL_DOWN = 0x10 +} GPIO_PUPD_FUNC; + void prev_raspi_pin_mode(GPIO_PIN pin, GPIO_FUNC mode); void prev_raspi_pin_write(GPIO_PIN pin, int pin_value); int rt_hw_gpio_init(void); diff --git a/bsp/raspberry-pi/raspi4-64/drivers/drv_gtimer.c b/bsp/raspberry-pi/raspi4-64/drivers/drv_gtimer.c new file mode 100644 index 0000000000..d8a1c77abd --- /dev/null +++ b/bsp/raspberry-pi/raspi4-64/drivers/drv_gtimer.c @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include "interrupt.h" + +#ifndef RT_CPUS_NR +#define RT_CPUS_NR 1 +#endif + +#define GTIMER_IRQ (27) + +static uint64_t _tickval[RT_CPUS_NR]; +static uint64_t _increaseval[RT_CPUS_NR]; +#define tickval _tickval[cpu_id] +#define increaseval _increaseval[cpu_id] + +/** + * This function is the gtimer isr handler. + * + * @param vector interrupt ID + * @param parameter the parameter specified by rt_hw_interrupt_install + * + * @return none + */ +static void _hw_timer_isr(int vector, void *parameter) +{ +#ifdef RT_USING_SMP + int cpu_id = rt_hw_cpu_id(); +#else + int cpu_id = 0; +#endif + uint64_t cntvct_el0; + do + { + tickval += increaseval; + __asm__ volatile("msr CNTV_CVAL_EL0, %0"::"r"(tickval)); + __asm__ volatile("mrs %0, CNTVCT_EL0":"=r"(cntvct_el0)); + } while (cntvct_el0 >= tickval); + rt_tick_increase(); +} + +/** + * The function will initialize the general timer used for the system tick. + * + * @param none + * + * @return none + */ +rt_weak int rt_hw_gtimer_init(void) +{ +#ifdef RT_USING_SMP + int cpu_id = rt_hw_cpu_id(); +#else + int cpu_id = 0; +#endif + uint64_t val; + + rt_hw_interrupt_install(GTIMER_IRQ, _hw_timer_isr, RT_NULL, "tick"); + rt_hw_interrupt_umask(GTIMER_IRQ); + + __asm__ volatile("mrs %0, CNTFRQ_EL0":"=r"(val)); + increaseval = val / RT_TICK_PER_SECOND; + + __asm__ volatile("msr CNTV_CTL_EL0, %0"::"r"(val)); + tickval = increaseval; + __asm__ volatile("msr CNTV_CVAL_EL0, %0"::"r"(tickval)); + val = 1; + __asm__ volatile("msr CNTV_CTL_EL0, %0"::"r"(val)); + return 0; +} +INIT_BOARD_EXPORT(rt_hw_gtimer_init); diff --git a/bsp/raspberry-pi/raspi4-64/drivers/drv_hdmi.c b/bsp/raspberry-pi/raspi4-64/drivers/drv_hdmi.c new file mode 100644 index 0000000000..1ba43e9a48 --- /dev/null +++ b/bsp/raspberry-pi/raspi4-64/drivers/drv_hdmi.c @@ -0,0 +1,353 @@ +/* + * Copyright (c) 2006-2020, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2020-10-26 bigmagic first version + */ + +#include +#include +#include + +#if defined(BSP_USING_HDMI) && defined(RT_USING_SMART) +#include +#include + +#include + +#include "mbox.h" +#include "drv_hdmi.h" + +#define LCD_WIDTH (800) +#define LCD_HEIGHT (480) +#define LCD_DEPTH (32) +#define LCD_BPP (32) + +#define TAG_ALLOCATE_BUFFER 0x00040001 +#define TAG_SET_PHYS_WIDTH_HEIGHT 0x00048003 +#define TAG_SET_VIRT_WIDTH_HEIGHT 0x00048004 +#define TAG_SET_DEPTH 0x00048005 +#define TAG_SET_PIXEL_ORDER 0x00048006 +#define TAG_GET_PITCH 0x00040008 +#define TAG_SET_VIRT_OFFSET 0x00048009 +#define TAG_END 0x00000000 + + +enum { + MBOX_TAG_FB_GET_GPIOVIRT = 0x00040010, + MBOX_TAG_FB_ALLOCATE_BUFFER = 0x00040001, + MBOX_TAG_FB_RELEASE_BUFFER = 0x00048001, + MBOX_TAG_FB_BLANK_SCREEN = 0x00040002, + MBOX_TAG_FB_GET_PHYS_WH = 0x00040003, + MBOX_TAG_FB_TEST_PHYS_WH = 0x00044003, + MBOX_TAG_FB_SET_PHYS_WH = 0x00048003, + MBOX_TAG_FB_GET_VIRT_WH = 0x00040004, + MBOX_TAG_FB_TEST_VIRT_WH = 0x00044004, + MBOX_TAG_FB_SET_VIRT_WH = 0x00048004, + MBOX_TAG_FB_GET_DEPTH = 0x00040005, + MBOX_TAG_FB_TEST_DEPTH = 0x00044005, + MBOX_TAG_FB_SET_DEPTH = 0x00048005, + MBOX_TAG_FB_GET_PIXEL_ORDER = 0x00040006, + MBOX_TAG_FB_TEST_PIXEL_ORDER = 0x00044006, + MBOX_TAG_FB_SET_PIXEL_ORDER = 0x00048006, + MBOX_TAG_FB_GET_ALPHA_MODE = 0x00040007, + MBOX_TAG_FB_TEST_ALPHA_MODE = 0x00044007, + MBOX_TAG_FB_SET_ALPHA_MODE = 0x00048007, + MBOX_TAG_FB_GET_PITCH = 0x00040008, + MBOX_TAG_FB_GET_VIRT_OFFSET = 0x00040009, + MBOX_TAG_FB_TEST_VIRT_OFFSET = 0x00044009, + MBOX_TAG_FB_SET_VIRT_OFFSET = 0x00048009, + MBOX_TAG_FB_GET_OVERSCAN = 0x0004000a, + MBOX_TAG_FB_TEST_OVERSCAN = 0x0004400a, + MBOX_TAG_FB_SET_OVERSCAN = 0x0004800a, + MBOX_TAG_FB_GET_PALETTE = 0x0004000b, + MBOX_TAG_FB_TEST_PALETTE = 0x0004400b, + MBOX_TAG_FB_SET_PALETTE = 0x0004800b, +}; + +#define LCD_DEVICE(dev) (struct rt_hdmi_fb_device*)(dev) + +static struct rt_hdmi_fb_device _hdmi; + +typedef rt_uint16_t color_t; + +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_ssize_t hdmi_fb_read(rt_device_t dev, rt_off_t pos, void *buf, rt_size_t size) +{ + return 0; +} + +rt_ssize_t hdmi_fb_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size) +{ + return size; +} + +rt_err_t hdmi_fb_control(rt_device_t dev, int cmd, void *args) +{ + static unsigned long smem_start = 0; + static unsigned long smem_len = 0; + struct rt_hdmi_fb_device *lcd = LCD_DEVICE(dev); + + switch (cmd) + { + case RTGRAPHIC_CTRL_RECT_UPDATE: + { + if (smem_start != 0) + { + rt_hw_cpu_dcache_clean_and_invalidate((void *)smem_start, smem_len); + } + } + break; + case RTGRAPHIC_CTRL_GET_INFO: + { + struct rt_device_graphic_info *lcd_info = (struct rt_device_graphic_info *)args; + lcd_info->bits_per_pixel = 32; + lcd_info->pixel_format = RTGRAPHIC_PIXEL_FORMAT_ARGB888; /* should be coherent to adding layers */ + lcd_info->width = lcd->width; + lcd_info->height = lcd->height; + lcd_info->framebuffer = (void *)lwp_map_user_phy(lwp_self(), RT_NULL, lcd->fb, lcd->width * lcd->height * sizeof(rt_uint32_t), 1); + } + break; +#define FBIOGET_FSCREENINFO 0x4602 + case FBIOGET_FSCREENINFO: + { + struct fb_fix_screeninfo + { + char id[16]; + unsigned long smem_start; + uint32_t smem_len; + + uint32_t line_length; + } *info = (struct fb_fix_screeninfo *)args; + rt_strncpy(info->id, "lcd", sizeof(info->id)); + info->smem_len = lcd->width * lcd->height * sizeof(rt_uint32_t); + info->smem_start = (size_t)lwp_map_user_phy(lwp_self(), RT_NULL, lcd->fb, info->smem_len, 1); + info->line_length = lcd->width * sizeof(rt_uint32_t); + rt_memset((void *)info->smem_start, 0, info->smem_len); + smem_start = info->smem_start; + smem_len = info->smem_len; + } + break; + } + return RT_EOK; +} + +#ifdef RT_USING_DEVICE_OPS +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, +}; +#endif + +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; + + /* 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; +} + +rt_uint32_t bcm271x_mbox_fb_get_gpiovirt(void) +{ + mbox[0] = 8*4; // length of the message + mbox[1] = MBOX_REQUEST; // this is a request message + + mbox[2] = MBOX_TAG_FB_GET_GPIOVIRT; + mbox[3] = 4; // buffer size + mbox[4] = 0; // len + + mbox[5] = 0; // id + mbox[6] = 0; + + mbox[7] = MBOX_TAG_LAST; + mbox_call(8, MMU_DISABLE); + return (mbox[5] & 0x3fffffff); +} + +rt_uint32_t bcm271x_mbox_fb_get_pitch(void) +{ + mbox[0] = 8*4; // length of the message + mbox[1] = MBOX_REQUEST; // this is a request message + + mbox[2] = MBOX_TAG_FB_GET_PITCH; + mbox[3] = 4; // buffer size + mbox[4] = 0; // len + + mbox[5] = 0; // id + mbox[6] = 0; + + mbox[7] = MBOX_TAG_LAST; + mbox_call(8, MMU_DISABLE); + return mbox[5]; +} + +void bcm271x_mbox_fb_set_porder(int rgb) +{ + mbox[0] = 8*4; // length of the message + mbox[1] = MBOX_REQUEST; // this is a request message + + mbox[2] = MBOX_TAG_FB_SET_PIXEL_ORDER; + mbox[3] = 4; // buffer size + mbox[4] = 4; // len + + mbox[5] = rgb; // id + mbox[6] = 0; + + mbox[7] = MBOX_TAG_LAST; + mbox_call(8, MMU_DISABLE); +} + +void bcm271x_mbox_fb_setoffset(int xoffset, int yoffset) +{ + mbox[0] = 8*4; // length of the message + mbox[1] = MBOX_REQUEST; // this is a request message + + mbox[2] = MBOX_TAG_FB_SET_VIRT_OFFSET; + mbox[3] = 8; // buffer size + mbox[4] = 8; // len + + mbox[5] = xoffset; // id + mbox[6] = yoffset; + + mbox[7] = MBOX_TAG_LAST; + mbox_call(8, MMU_DISABLE); +} + + +void bcm271x_mbox_fb_setalpha(int alpha) +{ + + mbox[0] = 8*4; // length of the message + mbox[1] = MBOX_REQUEST; // this is a request message + + mbox[2] = MBOX_TAG_FB_SET_ALPHA_MODE; + mbox[3] = 4; // buffer size + mbox[4] = 4; // len + + mbox[5] = alpha; // id + mbox[6] = 0; + + mbox[7] = MBOX_TAG_LAST; + mbox_call(8, MMU_DISABLE); +} + +void *bcm271x_mbox_fb_alloc(int width, int height, int bpp, int nrender) +{ + mbox[0] = 4 * 35; + mbox[1] = MBOX_REQUEST; + + mbox[2] = TAG_ALLOCATE_BUFFER;//get framebuffer, gets alignment on request + mbox[3] = 8; //size + mbox[4] = 4; //len + mbox[5] = 4096; //The design of MBOX driver forces us to give the virtual address 0x3C100000 + mbox[6] = 0; //FrameBufferInfo.size + + mbox[7] = TAG_SET_PHYS_WIDTH_HEIGHT; + mbox[8] = 8; + mbox[9] = 8; + mbox[10] = width; + mbox[11] = height; + + mbox[12] = TAG_SET_VIRT_WIDTH_HEIGHT; + mbox[13] = 8; + mbox[14] = 8; + mbox[15] = width; + mbox[16] = height * nrender; + + mbox[17] = TAG_SET_DEPTH; + mbox[18] = 4; + mbox[19] = 4; + mbox[20] = bpp; + + mbox[21] = TAG_SET_PIXEL_ORDER; + mbox[22] = 4; + mbox[23] = 0; + mbox[24] = 0; //RGB, not BGR preferably + + mbox[25] = TAG_GET_PITCH; + mbox[26] = 4; + mbox[27] = 0; + mbox[28] = 0; + + mbox[29] = TAG_SET_VIRT_OFFSET; + mbox[30] = 8; + mbox[31] = 8; + mbox[32] = 0; + mbox[33] = 0; + + mbox[34] = TAG_END; + + mbox_call(8, MMU_DISABLE); + return (void *)((size_t)(mbox[5] & 0x3fffffff)); +} + +int hdmi_fb_init(void) +{ + _hdmi.fb = (rt_uint8_t *)bcm271x_mbox_fb_alloc(LCD_WIDTH, LCD_HEIGHT, LCD_BPP, 1); + + if (_hdmi.fb == RT_NULL) + { + rt_kprintf("init hdmi fb err!\n"); + return -RT_ERROR; + } + +#ifdef BSP_USING_VM_MODE + if (rt_hv_stage2_map((unsigned long)_hdmi.fb, 0x1400000)) + { + rt_kprintf("alloc mmio from hyper fail!\n"); + return -RT_ERROR; + } +#endif + + bcm271x_mbox_fb_setoffset(0, 0); + bcm271x_mbox_fb_set_porder(0); + _hdmi.width = LCD_WIDTH; + _hdmi.height = LCD_HEIGHT; + _hdmi.depth = LCD_DEPTH; + _hdmi.pitch = 0; + _hdmi.pixel_format = RTGRAPHIC_PIXEL_FORMAT_RGB888; + + //rt_kprintf("_hdmi.fb is %p\n", _hdmi.fb); + rt_hdmi_fb_device_init(&_hdmi, "lcd"); + + return 0; +} + +INIT_DEVICE_EXPORT(hdmi_fb_init); +#endif /*BSP_USING_HDMI */ diff --git a/bsp/raspberry-pi/raspi4-64/drivers/drv_hdmi.h b/bsp/raspberry-pi/raspi4-64/drivers/drv_hdmi.h new file mode 100644 index 0000000000..c9a06358d0 --- /dev/null +++ b/bsp/raspberry-pi/raspi4-64/drivers/drv_hdmi.h @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2006-2020, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2020-10-26 bigmagic first version + */ +#ifndef __DRV_HDMI_H__ +#define __DRV_HDMI_H__ + +#define RGB(r, g, b) ((((r))<<16) | (((g))<<8) | ((b))) + +struct rt_hdmi_fb_device +{ + struct rt_device parent; + + rt_uint32_t width; + rt_uint32_t height; + rt_uint32_t depth; + rt_uint32_t pitch; + rt_uint32_t pixel_format; + + rt_uint8_t *fb; +}; +#endif/* __DRV_HDMI_H__ */ diff --git a/bsp/raspberry-pi/raspi4-64/driver/drv_sdio.c b/bsp/raspberry-pi/raspi4-64/drivers/drv_sdio.c similarity index 75% rename from bsp/raspberry-pi/raspi4-64/driver/drv_sdio.c rename to bsp/raspberry-pi/raspi4-64/drivers/drv_sdio.c index f80be13564..8359d1a00c 100644 --- a/bsp/raspberry-pi/raspi4-64/driver/drv_sdio.c +++ b/bsp/raspberry-pi/raspi4-64/drivers/drv_sdio.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2021, RT-Thread Development Team + * Copyright (c) 2006-2020, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * @@ -8,19 +8,13 @@ * 2020-10-27 bigmagic first version */ -#include #include "mbox.h" #include "raspi4.h" #include "drv_sdio.h" -#include "mmu.h" - -#ifdef BSP_USING_SDIO - static rt_uint32_t mmc_base_clock = 0; -static rt_uint32_t sdCommandTable[] = -{ +static rt_uint32_t sdCommandTable[] = { SD_CMD_INDEX(0), SD_CMD_RESERVED(1), SD_CMD_INDEX(2) | SD_RESP_R2, @@ -47,7 +41,7 @@ static rt_uint32_t sdCommandTable[] = 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(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, @@ -56,13 +50,13 @@ static rt_uint32_t sdCommandTable[] = 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_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_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), @@ -87,52 +81,46 @@ static rt_uint32_t sdCommandTable[] = SD_CMD_RESERVED(63) }; -rt_inline rt_uint32_t read32(rt_ubase_t addr) +static inline rt_uint32_t read32(size_t addr) { - return (*((volatile unsigned int *)(addr))); + return (*((volatile unsigned int*)(addr))); } -rt_inline void write32(rt_ubase_t addr, rt_uint32_t value) +static inline void write32(size_t addr, rt_uint32_t value) { - (*((volatile unsigned int *)(addr))) = value; + (*((volatile unsigned int*)(addr))) = value; } -rt_err_t sd_int(struct sdhci_pdata_t *pdat, rt_uint32_t mask) +rt_err_t sd_int(struct sdhci_pdata_t * pdat, rt_uint32_t mask) { rt_uint32_t r; rt_uint32_t m = mask | INT_ERROR_MASK; int cnt = 1000000; while (!(read32(pdat->virt + EMMC_INTERRUPT) & (m | INT_ERROR_MASK)) && cnt--) - { DELAY_MICROS(1); - } r = read32(pdat->virt + EMMC_INTERRUPT); if (cnt <= 0 || (r & INT_CMD_TIMEOUT) || (r & INT_DATA_TIMEOUT)) { write32(pdat->virt + EMMC_INTERRUPT, r); - /* qemu maybe can not use sdcard */ - rt_kprintf("send cmd/data timeout wait for %x int: %x, status: %x\n", mask, r, read32(pdat->virt + EMMC_STATUS)); - + //qemu maybe can not use sdcard + rt_kprintf("send cmd/data timeout wait for %x int: %x, status: %x\n",mask, r, read32(pdat->virt + EMMC_STATUS)); return -RT_ETIMEOUT; } else if (r & INT_ERROR_MASK) { write32(pdat->virt + EMMC_INTERRUPT, r); - rt_kprintf("send cmd/data error %x -> %x\n", r, read32(pdat->virt + EMMC_INTERRUPT)); - + 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) +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; @@ -145,7 +133,7 @@ rt_err_t sd_status(struct sdhci_pdata_t *pdat, unsigned int mask) return RT_EOK; } -static rt_err_t raspi_transfer_command(struct sdhci_pdata_t *pdat, struct sdhci_cmd_t *cmd) +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; @@ -158,30 +146,19 @@ static rt_err_t raspi_transfer_command(struct sdhci_pdata_t *pdat, struct sdhci_ 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_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) @@ -200,10 +177,10 @@ static rt_err_t raspi_transfer_command(struct sdhci_pdata_t *pdat, struct sdhci_ 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 ; + 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 { @@ -214,43 +191,34 @@ static rt_err_t raspi_transfer_command(struct sdhci_pdata_t *pdat, struct sdhci_ } } 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)); + 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) +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); + rt_kprintf("timeout happens when reading block %d\n",c); return ret; } - for (d = 0; d < blksize / 4; d++) - { + 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) +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; @@ -261,10 +229,8 @@ static rt_err_t write_bytes(struct sdhci_pdata_t *pdat, rt_uint32_t *buf, rt_uin { return ret; } - for (d = 0; d < blksize / 4; d++) - { + for (d=0; d < blksize / 4; d++) write32(pdat->virt + EMMC_DATA, buf[d]); - } c++; buf += blksize / 4; } @@ -273,15 +239,13 @@ static rt_err_t write_bytes(struct sdhci_pdata_t *pdat, rt_uint32_t *buf, rt_uin { 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) +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"); @@ -294,13 +258,10 @@ static rt_err_t raspi_transfer_data(struct sdhci_pdata_t *pdat, struct sdhci_cmd newcmd.cmdarg = dat->blkcnt; newcmd.resptype = RESP_R1; ret = raspi_transfer_command(pdat, &newcmd); - if (ret) - { - return ret; - } + if (ret) return ret; } - if (dlen < 512) + if(dlen < 512) { write32(pdat->virt + EMMC_BLKSIZECNT, dlen | 1 << 16); } @@ -312,34 +273,26 @@ static rt_err_t raspi_transfer_data(struct sdhci_pdata_t *pdat, struct sdhci_cmd { 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); + 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); + 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) +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; + 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); } @@ -356,7 +309,7 @@ static void mmc_request_send(struct rt_mmcsd_host *host, struct rt_mmcsd_req *re cmd.cmdidx = req->cmd->cmd_code; cmd.cmdarg = req->cmd->arg; - cmd.resptype = resp_type(req->cmd); + cmd.resptype =resp_type(req->cmd); if (req->data) { dat.buf = (rt_uint8_t *)req->data->buf; @@ -380,7 +333,7 @@ static void mmc_request_send(struct rt_mmcsd_host *host, struct rt_mmcsd_req *re { stop.cmdidx = req->stop->cmd_code; stop.cmdarg = req->stop->arg; - cmd.resptype = resp_type(req->stop); + cmd.resptype =resp_type(req->stop); req->stop->err = sdhci_transfer(sdhci, &stop, RT_NULL); } @@ -392,15 +345,15 @@ rt_int32_t mmc_card_status(struct rt_mmcsd_host *host) return 0; } -static rt_err_t sdhci_detect(struct sdhci_t *sdhci) +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) +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; + struct sdhci_pdata_t * pdat = (struct sdhci_pdata_t *)sdhci->priv; if (width == MMCSD_BUS_WIDTH_4) { temp = read32((pdat->virt + EMMC_CONTROL0)); @@ -412,26 +365,21 @@ static rt_err_t sdhci_setwidth(struct sdhci_t *sdhci, rt_uint32_t width) } -static uint32_t sd_get_clock_divider(rt_uint32_t sdHostVer, rt_uint32_t base_clock, rt_uint32_t target_rate) +static uint32_t sd_get_clock_divider(rt_uint32_t sdHostVer ,rt_uint32_t base_clock, rt_uint32_t target_rate) { rt_uint32_t targetted_divisor = 0; rt_uint32_t freq_select = 0; rt_uint32_t upper_bits = 0; rt_uint32_t ret = 0; - int divisor = -1; - if (target_rate > base_clock) - { + if(target_rate > base_clock) targetted_divisor = 1; - } else { targetted_divisor = base_clock / target_rate; rt_uint32_t mod = base_clock % target_rate; - if (mod) - { + if(mod) targetted_divisor--; - } } // Decide on the clock mode to use @@ -442,14 +390,15 @@ static uint32_t sd_get_clock_divider(rt_uint32_t sdHostVer, rt_uint32_t base_clo // This requires a power-of-two divider // Find the first bit set - for (int first_bit = 31; first_bit >= 0; first_bit--) + int divisor = -1; + for(int first_bit = 31; first_bit >= 0; first_bit--) { rt_uint32_t bit_test = (1 << first_bit); - if (targetted_divisor & bit_test) + if(targetted_divisor & bit_test) { divisor = first_bit; targetted_divisor &= ~bit_test; - if (targetted_divisor) + if(targetted_divisor) { // The divisor is not a power-of-two, increase it divisor++; @@ -458,24 +407,16 @@ static uint32_t sd_get_clock_divider(rt_uint32_t sdHostVer, rt_uint32_t base_clo } } - if (divisor == -1) - { + if(divisor == -1) divisor = 31; - } - if (divisor >= 32) - { + if(divisor >= 32) divisor = 31; - } - if (divisor != 0) - { + if(divisor != 0) divisor = (1 << (divisor - 1)); - } - if (divisor >= 0x400) - { + if(divisor >= 0x400) divisor = 0x3ff; - } freq_select = divisor & 0xff; upper_bits = (divisor >> 8) & 0x3; @@ -484,27 +425,25 @@ static uint32_t sd_get_clock_divider(rt_uint32_t sdHostVer, rt_uint32_t base_clo return ret; } -static rt_err_t sdhci_setclock(struct sdhci_t *sdhci, rt_uint32_t clock) +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); + 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; + 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); + 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); @@ -516,26 +455,23 @@ static rt_err_t sdhci_setclock(struct sdhci_t *sdhci, rt_uint32_t clock) temp |= (7 << 16); temp = (temp & 0xffff003f) | cdiv; - write32((pdat->virt + EMMC_CONTROL1), temp); + 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); + write32((pdat->virt + EMMC_CONTROL1),temp); DELAY_MICROS(10); - // wait for clock to be stable. + // 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; + return RT_ERROR; } mmcsd_dbg("set stable clock %d.\n", clock); @@ -544,7 +480,7 @@ static rt_err_t sdhci_setclock(struct sdhci_t *sdhci, rt_uint32_t clock) 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; + struct sdhci_t * sdhci = (struct sdhci_t *)host->private_data; sdhci_setclock(sdhci, io_cfg->clock); sdhci_setwidth(sdhci, io_cfg->bus_width); } @@ -557,30 +493,28 @@ static const struct rt_mmcsd_host_ops ops = RT_NULL, }; -static rt_err_t reset_emmc(struct sdhci_pdata_t *pdat) +static rt_err_t reset_emmc(struct sdhci_pdata_t * pdat) { rt_uint32_t control1; - int cnt = 10000; - /* reset the controller */ + //Reset the controller control1 = read32((pdat->virt + EMMC_CONTROL1)); control1 |= (1 << 24); - /* disable clock */ + // Disable clock control1 &= ~(1 << 2); control1 &= ~(1 << 0); - /* temp |= C1_CLK_INTLEN | C1_TOUNIT_MAX; */ - write32((pdat->virt + EMMC_CONTROL1), control1); - + //temp |= C1_CLK_INTLEN | C1_TOUNIT_MAX; + write32((pdat->virt + EMMC_CONTROL1),control1); + int cnt = 10000; do { DELAY_MICROS(10); - --cnt; - if (cnt == 0) + cnt = cnt - 1; + if(cnt == 0) { break; } - } - while ((read32(pdat->virt + EMMC_CONTROL1) & (0x7 << 24)) != 0); + } while ((read32(pdat->virt + EMMC_CONTROL1) & (0x7 << 24)) != 0); // Enable SD Bus Power VDD1 at 3.3V rt_uint32_t control0 = read32(pdat->virt + EMMC_CONTROL0); @@ -588,25 +522,25 @@ static rt_err_t reset_emmc(struct sdhci_pdata_t *pdat) write32(pdat->virt + EMMC_CONTROL0, control0); rt_thread_delay(100); + //usleep(2000); - /* check for a valid card */ + + // Check for a valid card mmcsd_dbg("EMMC: checking for an inserted card\n"); cnt = 10000; - do { DELAY_MICROS(10); - --cnt; - if (cnt == 0) + cnt = cnt - 1; + if(cnt == 0) { break; } - } - while ((read32(pdat->virt + EMMC_STATUS) & (0x1 << 16)) == 0); + } while ((read32(pdat->virt + EMMC_STATUS) & (0x1 << 16)) == 0); rt_uint32_t status_reg = read32(pdat->virt + EMMC_STATUS); - if ((status_reg & (1 << 16)) == 0) + if((status_reg & (1 << 16)) == 0) { rt_kprintf("EMMC: no card inserted\n"); return -1; @@ -616,30 +550,26 @@ static rt_err_t reset_emmc(struct sdhci_pdata_t *pdat) mmcsd_dbg("EMMC: status: %08x\n", status_reg); } - /* clear control2 */ + // Clear control2 write32(pdat->virt + EMMC_CONTROL2, 0); - /* get the base clock rate */ + // Get the base clock rate //12 mmc_base_clock = bcm271x_mbox_clock_get_rate(EMMC_CLK_ID); - if (mmc_base_clock == 0) + if(mmc_base_clock == 0) { rt_kprintf("EMMC: assuming clock rate to be 100MHz\n"); mmc_base_clock = 100000000; } mmcsd_dbg("EMMC: setting clock rate is %d\n", mmc_base_clock); - return RT_EOK; } #ifdef RT_MMCSD_DBG -void dump_registers(struct sdhci_pdata_t *pdat) +void dump_registers(struct sdhci_pdata_t * pdat) { - int i = EMMC_ARG2; - 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)); @@ -656,9 +586,9 @@ void dump_registers(struct sdhci_pdata_t *pdat) int raspi_sdmmc_init(void) { size_t virt; - struct rt_mmcsd_host *host = RT_NULL; - struct sdhci_pdata_t *pdat = RT_NULL; - struct sdhci_t *sdhci = RT_NULL; + 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(); @@ -675,7 +605,7 @@ int raspi_sdmmc_init(void) } rt_memset(sdhci, 0, sizeof(struct sdhci_t)); - virt = MMC2_BASE_ADDR; + virt = mmc2_base_addr; pdat = (struct sdhci_pdata_t *)rt_malloc(sizeof(struct sdhci_pdata_t)); RT_ASSERT(pdat != RT_NULL); @@ -703,9 +633,8 @@ int raspi_sdmmc_init(void) host->max_blk_count = 1; host->private_data = sdhci; - write32((pdat->virt + EMMC_IRPT_EN), 0xffffffff); - write32((pdat->virt + EMMC_IRPT_MASK), 0xffffffff); - + write32((pdat->virt + EMMC_IRPT_EN),0xffffffff); + write32((pdat->virt + EMMC_IRPT_MASK),0xffffffff); #ifdef RT_MMCSD_DBG dump_registers(pdat); #endif @@ -720,5 +649,3 @@ err: } INIT_DEVICE_EXPORT(raspi_sdmmc_init); - -#endif /* BSP_USING_SDIO */ diff --git a/bsp/raspberry-pi/raspi4-64/drivers/drv_sdio.h b/bsp/raspberry-pi/raspi4-64/drivers/drv_sdio.h new file mode 100644 index 0000000000..30d9d8d343 --- /dev/null +++ b/bsp/raspberry-pi/raspi4-64/drivers/drv_sdio.h @@ -0,0 +1,253 @@ +/* + * Copyright (c) 2006-2020, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2020-10-27 bigmagic first version + */ + +#ifndef __DRV_SDIO_H__ +#define __DRV_SDIO_H__ + +#include +#include +#include + +#include "board.h" +#include "raspi4.h" + +/* Struct for Intrrrupt Information */ +#define SDXC_CmdDone BIT(0) +#define SDXC_DataDone BIT(1) +#define SDXC_BlockGap BIT(2) +#define SDXC_WriteRdy BIT(4) +#define SDXC_ReadRdy BIT(5) +#define SDXC_Card BIT(8) +#define SDXC_Retune BIT(12) +#define SDXC_BootAck BIT(13) +#define SDXC_EndBoot BIT(14) +#define SDXC_Err BIT(15) +#define SDXC_CTOErr BIT(16) +#define SDXC_CCRCErr BIT(17) +#define SDXC_CENDErr BIT(18) +#define SDXC_CBADErr BIT(19) +#define SDXC_DTOErr BIT(20) +#define SDXC_DCRCErr BIT(21) +#define SDXC_DENDErr BIT(22) +#define SDXC_ACMDErr BIT(24) + +#define SDXC_BLKCNT_EN BIT(1) +#define SDXC_AUTO_CMD12_EN BIT(2) +#define SDXC_AUTO_CMD23_EN BIT(3) +#define SDXC_DAT_DIR BIT(4) //from card to host +#define SDXC_MULTI_BLOCK BIT(5) +#define SDXC_CMD_RSPNS_136 BIT(16) +#define SDXC_CMD_RSPNS_48 BIT(17) +#define SDXC_CMD_RSPNS_48busy BIT(16)|BIT(17) +#define SDXC_CHECK_CRC_CMD BIT(19) +#define SDXC_CMD_IXCHK_EN BIT(20) +#define SDXC_CMD_ISDATA BIT(21) +#define SDXC_CMD_SUSPEND BIT(22) +#define SDXC_CMD_RESUME BIT(23) +#define SDXC_CMD_ABORT BIT(23)|BIT(22) + +#define SDXC_CMD_INHIBIT BIT(0) +#define SDXC_DAT_INHIBIT BIT(1) +#define SDXC_DAT_ACTIVE BIT(2) +#define SDXC_WRITE_TRANSFER BIT(8) +#define SDXC_READ_TRANSFER BIT(9) + +struct sdhci_cmd_t +{ + rt_uint32_t cmdidx; + rt_uint32_t cmdarg; + rt_uint32_t resptype; + rt_uint32_t datarw; +#define DATA_READ 1 +#define DATA_WRITE 2 + rt_uint32_t response[4]; +}; + +struct sdhci_data_t +{ + rt_uint8_t * buf; + rt_uint32_t flag; + rt_uint32_t blksz; + rt_uint32_t blkcnt; +}; + +struct sdhci_t +{ + char * name; + rt_uint32_t voltages; + rt_uint32_t width; + rt_uint32_t clock; + rt_err_t removeable; + void * sdcard; + + rt_err_t (*detect)(struct sdhci_t * sdhci); + rt_err_t (*setwidth)(struct sdhci_t * sdhci, rt_uint32_t width); + rt_err_t (*setclock)(struct sdhci_t * sdhci, rt_uint32_t clock); + rt_err_t (*transfer)(struct sdhci_t * sdhci, struct sdhci_cmd_t * cmd, struct sdhci_data_t * dat); + void * priv; +}; + +struct sdhci_pdata_t +{ + size_t virt; +}; + +// EMMC command flags +#define CMD_TYPE_NORMAL (0x00000000) +#define CMD_TYPE_SUSPEND (0x00400000) +#define CMD_TYPE_RESUME (0x00800000) +#define CMD_TYPE_ABORT (0x00c00000) +#define CMD_IS_DATA (0x00200000) +#define CMD_IXCHK_EN (0x00100000) +#define CMD_CRCCHK_EN (0x00080000) +#define CMD_RSPNS_NO (0x00000000) +#define CMD_RSPNS_136 (0x00010000) +#define CMD_RSPNS_48 (0x00020000) +#define CMD_RSPNS_48B (0x00030000) +#define TM_MULTI_BLOCK (0x00000020) +#define TM_DAT_DIR_HC (0x00000000) +#define TM_DAT_DIR_CH (0x00000010) +#define TM_AUTO_CMD23 (0x00000008) +#define TM_AUTO_CMD12 (0x00000004) +#define TM_BLKCNT_EN (0x00000002) +#define TM_MULTI_DATA (CMD_IS_DATA|TM_MULTI_BLOCK|TM_BLKCNT_EN) + +#define RCA_NO (1) +#define RCA_YES (2) + +// INTERRUPT register settings +#define INT_AUTO_ERROR (0x01000000) +#define INT_DATA_END_ERR (0x00400000) +#define INT_DATA_CRC_ERR (0x00200000) +#define INT_DATA_TIMEOUT (0x00100000) +#define INT_INDEX_ERROR (0x00080000) +#define INT_END_ERROR (0x00040000) +#define INT_CRC_ERROR (0x00020000) +#define INT_CMD_TIMEOUT (0x00010000) +#define INT_ERR (0x00008000) +#define INT_ENDBOOT (0x00004000) +#define INT_BOOTACK (0x00002000) +#define INT_RETUNE (0x00001000) +#define INT_CARD (0x00000100) +#define INT_READ_RDY (0x00000020) +#define INT_WRITE_RDY (0x00000010) +#define INT_BLOCK_GAP (0x00000004) +#define INT_DATA_DONE (0x00000002) +#define INT_CMD_DONE (0x00000001) +#define INT_ERROR_MASK (INT_CRC_ERROR|INT_END_ERROR|INT_INDEX_ERROR| \ + INT_DATA_TIMEOUT|INT_DATA_CRC_ERR|INT_DATA_END_ERR| \ + INT_ERR|INT_AUTO_ERROR) +#define INT_ALL_MASK (INT_CMD_DONE|INT_DATA_DONE|INT_READ_RDY|INT_WRITE_RDY|INT_ERROR_MASK) + +#define EMMC_ARG2 (0x00) +#define EMMC_BLKSIZECNT (0x04) +#define EMMC_ARG1 (0x08) +#define EMMC_CMDTM (0x0c) +#define EMMC_RESP0 (0x10) +#define EMMC_RESP1 (0x14) +#define EMMC_RESP2 (0x18) +#define EMMC_RESP3 (0x1c) +#define EMMC_DATA (0x20) +#define EMMC_STATUS (0x24) +#define EMMC_CONTROL0 (0x28) +#define EMMC_CONTROL1 (0x2c) +#define EMMC_INTERRUPT (0x30) +#define EMMC_IRPT_MASK (0x34) +#define EMMC_IRPT_EN (0x38) +#define EMMC_CONTROL2 (0x3c) +#define EMMC_CAPABILITIES_0 (0x40) +#define EMMC_CAPABILITIES_1 (0x44) +#define EMMC_BOOT_TIMEOUT (0x70) +#define EMMC_EXRDFIFO_EN (0x84) +#define EMMC_SPI_INT_SPT (0xf0) +#define EMMC_SLOTISR_VER (0xfc) + +// CONTROL register settings +#define C0_SPI_MODE_EN (0x00100000) +#define C0_HCTL_HS_EN (0x00000004) +#define C0_HCTL_DWITDH (0x00000002) + +#define C1_SRST_DATA (0x04000000) +#define C1_SRST_CMD (0x02000000) +#define C1_SRST_HC (0x01000000) +#define C1_TOUNIT_DIS (0x000f0000) +#define C1_TOUNIT_MAX (0x000e0000) +#define C1_CLK_GENSEL (0x00000020) +#define C1_CLK_EN (0x00000004) +#define C1_CLK_STABLE (0x00000002) +#define C1_CLK_INTLEN (0x00000001) + +#define FREQ_SETUP (400000) // 400 Khz +#define FREQ_NORMAL (25000000) // 25 Mhz + +// SLOTISR_VER values +#define HOST_SPEC_NUM 0x00ff0000 +#define HOST_SPEC_NUM_SHIFT 16 +#define HOST_SPEC_V3 2 +#define HOST_SPEC_V2 1 +#define HOST_SPEC_V1 0 + +// STATUS register settings +#define SR_DAT_LEVEL1 (0x1e000000) +#define SR_CMD_LEVEL (0x01000000) +#define SR_DAT_LEVEL0 (0x00f00000) +#define SR_DAT3 (0x00800000) +#define SR_DAT2 (0x00400000) +#define SR_DAT1 (0x00200000) +#define SR_DAT0 (0x00100000) +#define SR_WRITE_PROT (0x00080000) // From SDHC spec v2, BCM says reserved +#define SR_READ_AVAILABLE (0x00000800) // ???? undocumented +#define SR_WRITE_AVAILABLE (0x00000400) // ???? undocumented +#define SR_READ_TRANSFER (0x00000200) +#define SR_WRITE_TRANSFER (0x00000100) +#define SR_DAT_ACTIVE (0x00000004) +#define SR_DAT_INHIBIT (0x00000002) +#define SR_CMD_INHIBIT (0x00000001) + +#define CONFIG_MMC_USE_DMA +#define DMA_ALIGN (32U) + +#define SD_CMD_INDEX(a) ((a) << 24) +#define SD_CMD_RESERVED(a) (0xffffffff) +#define SD_CMD_INDEX(a) ((a) << 24) +#define SD_CMD_TYPE_NORMAL (0x0) +#define SD_CMD_TYPE_SUSPEND (1 << 22) +#define SD_CMD_TYPE_RESUME (2 << 22) +#define SD_CMD_TYPE_ABORT (3 << 22) +#define SD_CMD_TYPE_MASK (3 << 22) +#define SD_CMD_ISDATA (1 << 21) +#define SD_CMD_IXCHK_EN (1 << 20) +#define SD_CMD_CRCCHK_EN (1 << 19) +#define SD_CMD_RSPNS_TYPE_NONE (0) // For no response +#define SD_CMD_RSPNS_TYPE_136 (1 << 16) // For response R2 (with CRC), R3,4 (no CRC) +#define SD_CMD_RSPNS_TYPE_48 (2 << 16) // For responses R1, R5, R6, R7 (with CRC) +#define SD_CMD_RSPNS_TYPE_48B (3 << 16) // For responses R1b, R5b (with CRC) +#define SD_CMD_RSPNS_TYPE_MASK (3 << 16) +#define SD_CMD_MULTI_BLOCK (1 << 5) +#define SD_CMD_DAT_DIR_HC (0) +#define SD_CMD_DAT_DIR_CH (1 << 4) +#define SD_CMD_AUTO_CMD_EN_NONE (0) +#define SD_CMD_AUTO_CMD_EN_CMD12 (1 << 2) +#define SD_CMD_AUTO_CMD_EN_CMD23 (2 << 2) +#define SD_CMD_BLKCNT_EN (1 << 1) +#define SD_CMD_DMA (1) +#define SD_RESP_NONE SD_CMD_RSPNS_TYPE_NONE +#define SD_RESP_R1 (SD_CMD_RSPNS_TYPE_48) // | 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/raspi4-64/drivers/drv_spi.c b/bsp/raspberry-pi/raspi4-64/drivers/drv_spi.c new file mode 100644 index 0000000000..0ca6b8c1a5 --- /dev/null +++ b/bsp/raspberry-pi/raspi4-64/drivers/drv_spi.c @@ -0,0 +1,296 @@ +/* + * Copyright (c) 2006-2020, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2020-06-22 bigmagic first version + */ +#include +#include +#include + +#include "raspi4.h" +#include "drv_spi.h" + +#ifdef BSP_USING_SPI + +#define RPI_CORE_CLK_HZ (250000000) +#define BSP_SPI_MAX_HZ (30* 1000 *1000) +#define SPITIMEOUT 0x0FFF + +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 +}; + +#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) +static struct rt_spi_device spi0_device0; +#endif + +#if defined (BSP_USING_SPI0_DEVICE1) +static struct rt_spi_device spi0_device1; +#endif +#endif + +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; + struct raspi_spi_device* hw_config = (struct raspi_spi_device *)(device->parent.user_data); + struct raspi_spi_hw_config *hwcfg = (struct raspi_spi_hw_config *)hw_config->spi_hw_config; + // spi clear fifo + SPI_REG_CS(hwcfg->hw_base) = (SPI_CS_CLEAR_TX | SPI_CS_CLEAR_RX); + if(cfg->mode & RT_SPI_CPOL) + { + SPI_REG_CS(hwcfg->hw_base) |= SPI_CS_CPOL; + } + + if(cfg->mode & RT_SPI_CPHA) + { + SPI_REG_CS(hwcfg->hw_base) |= SPI_CS_CPHA; + } + + if(cfg->mode & RT_SPI_CS_HIGH) + { + SPI_REG_CS(hwcfg->hw_base) |= SPI_CS_CSPOL_HIGH; + } + + //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; + + SPI_REG_CLK(hwcfg->hw_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];//reverse + else + return b; +} + +static rt_err_t spi_transfernb(struct raspi_spi_hw_config *hwcfg, 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 */ + SPI_REG_CS(hwcfg->hw_base) |= (SPI_CS_CLEAR_TX | SPI_CS_CLEAR_RX); + + /* Set TA = 1 */ + SPI_REG_CS(hwcfg->hw_base) |= SPI_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 (((SPI_REG_CS(hwcfg->hw_base) & SPI_CS_TX_DATA)) && (TXCnt < len)) + { + SPI_REG_FIFO(hwcfg->hw_base) = correct_order(tbuf[TXCnt],flag); + TXCnt++; + } + /* Rx fifo not empty, so get the next received bytes */ + while (((SPI_REG_CS(hwcfg->hw_base) & SPI_CS_RX_DATA)) && (RXCnt < len)) + { + rbuf[RXCnt] = correct_order(SPI_REG_FIFO(hwcfg->hw_base), flag); + RXCnt++; + } + } + /* Wait for DONE to be set */ + while (!(SPI_REG_CS(hwcfg->hw_base) & SPI_CS_DONE)); + /* Set TA = 0, and also set the barrier */ + SPI_REG_CS(hwcfg->hw_base) |= (0 & SPI_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_uint8_t flag; + 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); + + struct rt_spi_configuration config = device->config; + struct raspi_spi_device * hw_config = (struct raspi_spi_device *)device->parent.user_data; + GPIO_PIN cs_pin = (GPIO_PIN)hw_config->cs_pin; + struct raspi_spi_hw_config *hwcfg = (struct raspi_spi_hw_config *)hw_config->spi_hw_config; + + if (config.mode & RT_SPI_MSB) + { + flag = 0; + } + else + { + flag = 1; + } + + if (message->cs_take) + { + (config.mode & RT_SPI_CS_HIGH)?prev_raspi_pin_write(cs_pin, 1):prev_raspi_pin_write(cs_pin, 0); + } + + res = spi_transfernb(hwcfg, (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)?prev_raspi_pin_write(cs_pin, 0):prev_raspi_pin_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)); + return ret; +} + +rt_err_t raspi_spi_hw_init(struct raspi_spi_hw_config *hwcfg) +{ + prev_raspi_pin_mode(hwcfg->sclk_pin, hwcfg->sclk_mode); + prev_raspi_pin_mode(hwcfg->miso_pin, hwcfg->miso_mode); + prev_raspi_pin_mode(hwcfg->mosi_pin, hwcfg->mosi_mode); +#if defined (BSP_USING_SPI0_DEVICE0) + prev_raspi_pin_mode(hwcfg->ce0_pin, hwcfg->ce0_mode); +#endif + +#if defined (BSP_USING_SPI0_DEVICE1) + prev_raspi_pin_mode(hwcfg->ce1_pin, hwcfg->ce1_mode); +#endif + //clear rx and tx + SPI_REG_CS(hwcfg->hw_base) = (SPI_CS_CLEAR_TX | SPI_CS_CLEAR_RX); + //enable chip select +#if defined (BSP_USING_SPI0_DEVICE0) + SPI_REG_CS(hwcfg->hw_base) |= SPI_CS_CHIP_SELECT_0; +#endif + +#if defined (BSP_USING_SPI0_DEVICE1) + SPI_REG_CS(hwcfg->hw_base) |= SPI_CS_CHIP_SELECT_1; +#endif + +#if defined (BSP_USING_SPI0_DEVICE0) && defined (BSP_USING_SPI0_DEVICE1) + HWREG32(SPI_REG_CS(hwcfg->hw_base)) |= (SPI_CS_CHIP_SELECT_0 | SPI_CS_CHIP_SELECT_1); +#endif + return RT_EOK; +} + +static struct rt_spi_ops raspi_spi_ops = +{ + .configure = raspi_spi_configure, + .xfer = raspi_spi_xfer +}; + +struct raspi_spi_hw_config raspi_spi0_hw = +{ + .spi_num = 0, + .sclk_pin = GPIO_PIN_11, + .sclk_mode = ALT0, + .mosi_pin = GPIO_PIN_10, + .mosi_mode = ALT0, + .miso_pin = GPIO_PIN_9, + .miso_mode = ALT0, + +#if defined (BSP_USING_SPI0_DEVICE0) + .ce0_pin = GPIO_PIN_8, + .ce0_mode = ALT0, +#endif + +#if defined (BSP_USING_SPI0_DEVICE1) + .ce1_pin = GPIO_PIN_7, + .ce1_mode = ALT0, +#endif + .hw_base = SPI_0_BASE, +}; +#endif + +#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, + .spi_hw_config = &raspi_spi0_hw, + .cs_pin = GPIO_PIN_8, +}; +#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 = GPIO_PIN_7, +}; +#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) + raspi_spi_bus_attach_device(SPI0_BUS_NAME, &raspi_spi0_device0); +#endif + +#if defined (BSP_USING_SPI0_DEVICE1) + raspi_spi_bus_attach_device(SPI0_BUS_NAME, &raspi_spi0_device1); +#endif +#endif + return RT_EOK; +} +INIT_DEVICE_EXPORT(rt_hw_spi_init); diff --git a/bsp/raspberry-pi/raspi4-64/drivers/drv_spi.h b/bsp/raspberry-pi/raspi4-64/drivers/drv_spi.h new file mode 100644 index 0000000000..80876a43c6 --- /dev/null +++ b/bsp/raspberry-pi/raspi4-64/drivers/drv_spi.h @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2006-2020, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2020-06-16 bigmagic first version + */ +#ifndef __DRV_SPI_H__ +#define __DRV_SPI_H__ + +#include "drv_gpio.h" + +#define SPI_REG_CS(BASE) HWREG32(BASE + 0x00) +#define SPI_REG_FIFO(BASE) HWREG32(BASE + 0x04) +#define SPI_REG_CLK(BASE) HWREG32(BASE + 0x08) +#define SPI_REG_DLEN(BASE) HWREG32(BASE + 0x0C) +#define SPI_REG_LTOH(BASE) HWREG32(BASE + 0x10) +#define SPI_REG_DC(BASE) HWREG32(BASE + 0x14) + +/* CS Register */ +#define SPI_CS_LOSSI_LONG_32BIT (1 << 25) +#define SPI_CS_LOSSI_DMA_MODE (1 << 24) +#define SPI_CS_CSPOL2 (1 << 23) +#define SPI_CS_CSPOL1 (1 << 22) +#define SPI_CS_CSPOL0 (1 << 21) +#define SPI_CS_RX_FIFO_FULL (1 << 20) +#define SPI_CS_RX_FIFO_3_QUARTER (1 << 19) +#define SPI_CS_TX_DATA (1 << 18) +#define SPI_CS_RX_DATA (1 << 17) +#define SPI_CS_DONE (1 << 16) +#define SPI_CS_LOSSI_EN (1 << 13) +#define SPI_CS_READ_EN (1 << 12) +#define SPI_CS_AUTO_CS (1 << 11) +#define SPI_CS_INTR_RXR (1 << 10) +#define SPI_CS_INTR_DONE (1 << 9) +#define SPI_CS_DMA_EN (1 << 8) +#define SPI_CS_TA (1 << 7) +#define SPI_CS_CSPOL_HIGH (1 << 6) +#define SPI_CS_CLEAR_RX (2 << 4) +#define SPI_CS_CLEAR_TX (1 << 4) +#define SPI_CS_CPOL (1 << 3) +#define SPI_CS_CPHA (1 << 2) +#define SPI_CS_CHIP_SELECT_2 (2 << 0) +#define SPI_CS_CHIP_SELECT_1 (1 << 0) +#define SPI_CS_CHIP_SELECT_0 (0 << 0) + +struct raspi_spi_hw_config +{ + rt_uint8_t spi_num; + GPIO_PIN sclk_pin; + GPIO_FUNC sclk_mode; + GPIO_PIN mosi_pin; + GPIO_FUNC mosi_mode; + GPIO_PIN miso_pin; + GPIO_FUNC miso_mode; +#if defined (BSP_USING_SPI0_DEVICE0) || defined (BSP_USING_SPI1_DEVICE0) + GPIO_PIN ce0_pin; + GPIO_FUNC ce0_mode; +#endif + +#if defined (BSP_USING_SPI0_DEVICE1) || defined (BSP_USING_SPI1_DEVICE1) + GPIO_PIN ce1_pin; + GPIO_FUNC ce1_mode; +#endif + +#if defined (BSP_USING_SPI1_DEVICE2) + GPIO_PIN ce2_pin; + GPIO_FUNC ce2_mode; +#endif + rt_ubase_t hw_base; + +}; + +struct raspi_spi_device +{ + char *device_name; + struct rt_spi_bus *spi_bus; + struct rt_spi_device *spi_device; + struct raspi_spi_hw_config *spi_hw_config; + GPIO_PIN cs_pin; +}; + +int rt_hw_spi_init(void); + +#endif diff --git a/bsp/raspberry-pi/raspi4-64/driver/drv_uart.c b/bsp/raspberry-pi/raspi4-64/drivers/drv_uart.c similarity index 83% rename from bsp/raspberry-pi/raspi4-64/driver/drv_uart.c rename to bsp/raspberry-pi/raspi4-64/drivers/drv_uart.c index 195912268a..2479d3e644 100644 --- a/bsp/raspberry-pi/raspi4-64/driver/drv_uart.c +++ b/bsp/raspberry-pi/raspi4-64/drivers/drv_uart.c @@ -1,11 +1,12 @@ /* - * Copyright (c) 2006-2021, RT-Thread Development Team + * Copyright (c) 2006-2023, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * * Change Logs: * Date Author Notes * 2020-04-16 bigmagic first version + * 2020-05-26 bigmagic add other uart */ #include @@ -15,12 +16,12 @@ #include "board.h" #include "drv_uart.h" #include "drv_gpio.h" +#include -struct hw_uart_device -{ - rt_ubase_t hw_base; - rt_uint32_t irqno; -}; +size_t uart0_addr = 0; +size_t uart3_addr = 0; +size_t uart4_addr = 0; +size_t uart5_addr = 0; #ifdef RT_USING_UART0 static struct rt_serial_device _serial0; @@ -42,6 +43,12 @@ static struct rt_serial_device _serial4; static struct rt_serial_device _serial5; #endif +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; @@ -67,25 +74,25 @@ static rt_err_t uart_configure(struct rt_serial_device *serial, struct serial_co return RT_EOK; } - if(uart->hw_base == UART0_BASE) + if(uart->hw_base == uart0_addr) { prev_raspi_pin_mode(GPIO_PIN_14, ALT0); prev_raspi_pin_mode(GPIO_PIN_15, ALT0); } - if(uart->hw_base == UART3_BASE) + if(uart->hw_base == uart3_addr) { prev_raspi_pin_mode(GPIO_PIN_4, ALT4); prev_raspi_pin_mode(GPIO_PIN_5, ALT4); } - if(uart->hw_base == UART4_BASE) + if(uart->hw_base == uart4_addr) { prev_raspi_pin_mode(GPIO_PIN_8, ALT4); prev_raspi_pin_mode(GPIO_PIN_9, ALT4); } - if(uart->hw_base == UART5_BASE) + if(uart->hw_base == uart5_addr) { prev_raspi_pin_mode(GPIO_PIN_12, ALT4); prev_raspi_pin_mode(GPIO_PIN_13, ALT4); @@ -107,13 +114,9 @@ static rt_err_t uart_control(struct rt_serial_device *serial, int cmd, void *arg 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 */ - PL011_REG_IMSC(uart->hw_base) &= ~((uint32_t)PL011_IMSC_RXIM); - rt_hw_interrupt_mask(uart->irqno); break; case RT_DEVICE_CTRL_SET_INT: @@ -129,17 +132,14 @@ static rt_err_t uart_control(struct rt_serial_device *serial, int cmd, void *arg 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; - if(uart->hw_base == AUX_BASE) { while (!(AUX_MU_LSR_REG(uart->hw_base) & 0x20)); @@ -150,7 +150,6 @@ static int uart_putc(struct rt_serial_device *serial, char c) while ((PL011_REG_FR(uart->hw_base) & PL011_FR_TXFF)); PL011_REG_DR(uart->hw_base) = (uint8_t)c; } - return 1; } @@ -188,10 +187,50 @@ static const struct rt_uart_ops _uart_ops = uart_getc, }; +void *earlycon_base = (void *)AUX_BASE; +size_t earlycon_size = 0x1000; + +extern void early_putc(int c) +{ + if (c == '\n') + { + early_putc('\r'); + } + while (!(AUX_MU_LSR_REG(earlycon_base) & 0x20)); + AUX_MU_IO_REG(earlycon_base) = c; +} + +void rt_hw_console_output(const char *str) +{ + if (earlycon_base) + { + while (*str) + { + early_putc(*str++); + } + } +} + +void early_printhex(rt_ubase_t number) +{ + char str[sizeof("0123456789abcdef")]; + + str[16] = 0; + + for (int i = 15; i >= 0; --i) + { + str[i] = "0123456789abcdef"[(number & 0xf)]; + + number >>= 4; + } + + rt_kputs(str); +} + #ifdef RT_USING_UART1 static void rt_hw_aux_uart_isr(int irqno, void *param) { - struct rt_serial_device *serial = (struct rt_serial_device*)param; + struct rt_serial_device *serial = (struct rt_serial_device*)param; rt_hw_serial_isr(serial, RT_SERIAL_EVENT_RX_IND); } #endif @@ -200,10 +239,10 @@ static void rt_hw_uart_isr(int irqno, void *param) { #ifdef RT_USING_UART0 if((PACTL_CS & IRQ_UART0) == IRQ_UART0) - { + { PACTL_CS &= ~(IRQ_UART0); rt_hw_serial_isr(&_serial0, RT_SERIAL_EVENT_RX_IND); - PL011_REG_ICR(UART0_BASE) = PL011_INTERRUPT_RECEIVE; + PL011_REG_ICR(uart0_addr) = PL011_INTERRUPT_RECEIVE; } #endif @@ -277,8 +316,6 @@ static struct hw_uart_device _uart5_device = }; #endif -static struct rt_serial_device _serial0; - int rt_hw_uart_init(void) { struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT; @@ -289,15 +326,20 @@ int rt_hw_uart_init(void) _serial0.ops = &_uart_ops; _serial0.config = config; - uart0->hw_base = UART0_BASE; - + uart0_addr = UART0_BASE; +#ifdef RT_USING_SMART + uart0_addr = (size_t)rt_ioremap((void*)UART0_BASE, 0x1000); +#endif + earlycon_base = (void *)uart0_addr; + uart0->hw_base = uart0_addr; + /* register UART0 device */ rt_hw_serial_register(&_serial0, "uart0", RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX, uart0); rt_hw_interrupt_install(uart0->irqno, rt_hw_uart_isr, &_serial0, "uart0"); - + #endif #ifdef RT_USING_UART1 @@ -306,8 +348,8 @@ int rt_hw_uart_init(void) _serial1.ops = &_uart_ops; _serial1.config = config; - - uart1->hw_base = AUX_BASE; + + uart1->hw_base = (size_t)rt_ioremap((void*)AUX_BASE, 0x1000); /* register UART1 device */ rt_hw_serial_register(&_serial1, "uart1", @@ -323,7 +365,8 @@ int rt_hw_uart_init(void) _serial3.ops = &_uart_ops; _serial3.config = config; - uart3_addr = UART3_BASE; + uart3_addr = (size_t)rt_ioremap((void*)UART3_BASE, 0x1000); + uart3->hw_base = uart3_addr; /* register UART3 device */ rt_hw_serial_register(&_serial3, "uart3", @@ -339,7 +382,8 @@ int rt_hw_uart_init(void) _serial4.ops = &_uart_ops; _serial4.config = config; - uart4_addr = UART4_BASE; + uart4_addr = (size_t)rt_ioremap((void*)UART4_BASE, 0x1000); + uart4->hw_base = uart4_addr; /* register UART4 device */ rt_hw_serial_register(&_serial4, "uart4", @@ -355,7 +399,8 @@ int rt_hw_uart_init(void) _serial5.ops = &_uart_ops; _serial5.config = config; - uart5_addr = UART5_BASE; + uart5_addr = (size_t)rt_ioremap((void*)UART5_BASE, 0x1000); + uart5->hw_base = uart5_addr; /* register UART5 device */ rt_hw_serial_register(&_serial5, "uart5", @@ -365,3 +410,4 @@ int rt_hw_uart_init(void) #endif return 0; } + diff --git a/bsp/raspberry-pi/raspi4-64/driver/drv_uart.h b/bsp/raspberry-pi/raspi4-64/drivers/drv_uart.h similarity index 61% rename from bsp/raspberry-pi/raspi4-64/driver/drv_uart.h rename to bsp/raspberry-pi/raspi4-64/drivers/drv_uart.h index 56cfd9dcc6..8961200453 100644 --- a/bsp/raspberry-pi/raspi4-64/driver/drv_uart.h +++ b/bsp/raspberry-pi/raspi4-64/drivers/drv_uart.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2021, RT-Thread Development Team + * Copyright (c) 2006-2023, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * @@ -81,26 +81,26 @@ /* * 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 */ +#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); diff --git a/bsp/raspberry-pi/raspi4-64/driver/drv_wdt.c b/bsp/raspberry-pi/raspi4-64/drivers/drv_wdt.c similarity index 65% rename from bsp/raspberry-pi/raspi4-64/driver/drv_wdt.c rename to bsp/raspberry-pi/raspi4-64/drivers/drv_wdt.c index 13ef095b03..3c091354bb 100644 --- a/bsp/raspberry-pi/raspi4-64/driver/drv_wdt.c +++ b/bsp/raspberry-pi/raspi4-64/drivers/drv_wdt.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2021, RT-Thread Development Team + * Copyright (c) 2006-2020, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * @@ -7,11 +7,8 @@ * Date Author Notes * 2020-10-26 bigmagic first version */ - #include #include "drv_wdt.h" -#include "drv_gpio.h" -#include "mbox.h" #include "raspi4.h" #ifdef BSP_USING_WDT @@ -62,26 +59,22 @@ rt_uint64_t raspi_watchdog_get_timeleft() static rt_err_t raspi_wdg_init(rt_watchdog_t *wdt) { - /* init for 10S */ + /*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; - + 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: @@ -102,9 +95,8 @@ static rt_err_t raspi_wdg_control(rt_watchdog_t *wdt, int cmd, void *arg) raspi_watchdog_stop(); break; default: - return -RT_EIO; + return RT_EIO; } - return RT_EOK; } @@ -124,48 +116,6 @@ int rt_hw_wdt_init(void) } INIT_DEVICE_EXPORT(rt_hw_wdt_init); -void poweroff(void) -{ - unsigned long r; - - rt_kprintf("poweroff...\n"); - - /* power off devices one by one */ - for (r = 0; r < 16; ++r) - { - bcm271x_mbox_poweroff_devices(r); - } - - /* power off gpio pins (but not VCC pins) */ - GPIO_REG_GPFSEL0(GPIO_BASE) = 0; - GPIO_REG_GPFSEL1(GPIO_BASE) = 0; - GPIO_REG_GPFSEL2(GPIO_BASE) = 0; - GPIO_REG_GPFSEL3(GPIO_BASE) = 0; - GPIO_REG_GPFSEL4(GPIO_BASE) = 0; - GPIO_REG_GPFSEL5(GPIO_BASE) = 0; - GPIO_REG_GPPUD(GPIO_BASE) = 0; - rt_thread_mdelay(150); - - GPIO_REG_GPPUDCLK0(GPIO_BASE) = 0xffffffff; - GPIO_REG_GPPUDCLK1(GPIO_BASE) = 0xffffffff; - rt_thread_mdelay(150); - - /* flush GPIO setup */ - GPIO_REG_GPPUDCLK0(GPIO_BASE) = 0; - GPIO_REG_GPPUDCLK1(GPIO_BASE) = 0; - - /* power off the SoC (GPU + CPU), partition 63 used to indicate halt */ - r = PM_RSTS; - r &= ~0xfffffaaa; - r |= 0x555; - PM_RSTS |= PM_PASSWORD | r; - PM_WDOG |= PM_PASSWORD | 0x0A; - PM_RSTC |= PM_PASSWORD | PM_RSTC_WRCFG_FULL_RESET; - - while (1) {}; -} -MSH_CMD_EXPORT(poweroff, poweroff...); - void reboot(void) { unsigned int r; @@ -173,13 +123,13 @@ void reboot(void) rt_kprintf("reboot system...\n"); rt_thread_mdelay(100); r = PM_RSTS; - /* trigger a restart by instructing the GPU to boot from partition 0 */ + // trigger a restart by instructing the GPU to boot from partition 0 r &= ~0xfffffaaa; - PM_RSTS |= (PM_PASSWORD | r); /* boot from partition 0 */ + PM_RSTS |= (PM_PASSWORD | r); // boot from partition 0 PM_WDOG |= (PM_PASSWORD | 0x0A); PM_RSTC |= (PM_PASSWORD | PM_RSTC_WRCFG_FULL_RESET); - - while (1) {}; + + while (1); } -MSH_CMD_EXPORT(reboot, reboot system...); +MSH_CMD_EXPORT(reboot,reboot system...); #endif /*BSP_USING_WDT */ diff --git a/bsp/raspberry-pi/raspi4-64/driver/drv_wdt.h b/bsp/raspberry-pi/raspi4-64/drivers/drv_wdt.h similarity index 86% rename from bsp/raspberry-pi/raspi4-64/driver/drv_wdt.h rename to bsp/raspberry-pi/raspi4-64/drivers/drv_wdt.h index bbbaeab232..58c48d3d77 100644 --- a/bsp/raspberry-pi/raspi4-64/driver/drv_wdt.h +++ b/bsp/raspberry-pi/raspi4-64/drivers/drv_wdt.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2021, RT-Thread Development Team + * Copyright (c) 2006-2023, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * @@ -7,7 +7,6 @@ * Date Author Notes * 2020-10-26 bigmagic first version */ - #ifndef __DRV_WDT_H__ #define __DRV_WDT_H__ diff --git a/bsp/raspberry-pi/raspi4-64/driver/mbox.c b/bsp/raspberry-pi/raspi4-64/drivers/mbox.c similarity index 72% rename from bsp/raspberry-pi/raspi4-64/driver/mbox.c rename to bsp/raspberry-pi/raspi4-64/drivers/mbox.c index c497c6365f..0bbbdd6665 100644 --- a/bsp/raspberry-pi/raspi4-64/driver/mbox.c +++ b/bsp/raspberry-pi/raspi4-64/drivers/mbox.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2021, RT-Thread Development Team + * Copyright (c) 2006-2023, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * @@ -10,42 +10,39 @@ */ /* mailbox message buffer */ +#include #include "mbox.h" #include "mmu.h" +//volatile unsigned int __attribute__((aligned(16))) mbox[36]; -volatile unsigned int *mbox = (volatile unsigned int *) MBOX_ADDR; -#define BUS_ADDRESS(phys) (((phys) & ~0xC0000000) | 0xC0000000) +#define BUS_ADDRESS(phys) (((phys) & ~0xC0000000) | 0xC0000000) +volatile unsigned int *mbox; /** * Make a mailbox call. Returns 0 on failure, non-zero on success */ int mbox_call(unsigned char ch, int mmu_enable) { - unsigned int r = (((MBOX_ADDR) & ~0xF) | (ch & 0xF)); - if (mmu_enable) - { + unsigned int r = ((((rt_uint32_t)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); + 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) + while(1) { /* is there a response? */ do { - __asm__ volatile ("nop"); - } - while (*MBOX_STATUS & MBOX_EMPTY); + asm volatile("nop"); + } while (*MBOX_STATUS & MBOX_EMPTY); /* is it a response to our message? */ - if (r == *MBOX_READ) - { + if (r == *MBOX_READ){ /* is it a valid successful response? */ return mbox[1] == MBOX_RESPONSE; } @@ -53,74 +50,56 @@ int mbox_call(unsigned char ch, int mmu_enable) return 0; } -int bcm271x_mbox_poweroff_devices(int id) -{ - mbox[0] = 8 * 4; /* length of the message */ - mbox[1] = MBOX_REQUEST; /* this is a request message */ - - mbox[2] = MBOX_TAG_SETPOWER; /* set power state */ - mbox[3] = 8; /* buffer size */ - mbox[4] = 8; /* len */ - - mbox[5] = (unsigned int)id; /* device id */ - mbox[6] = 0; /* bit 0: off, bit 1: no wait */ - - mbox[7] = MBOX_TAG_LAST; - mbox_call(8, MBOX_CH_PROP); - - return 0; -} - int bcm271x_mbox_get_touch(void) { - mbox[0] = 8 * 4; // length of the message - mbox[1] = MBOX_REQUEST; // this is a request message + mbox[0] = 8 * 4; // length of the message + mbox[1] = MBOX_REQUEST; // this is a request message mbox[2] = MBOX_TAG_GET_TOUCHBUF; - mbox[3] = 4; // buffer size - mbox[4] = 0; // len + mbox[3] = 4; // buffer size + mbox[4] = 0; // len - mbox[5] = 0; // id + mbox[5] = 0; // id mbox[6] = 0; mbox[7] = MBOX_TAG_LAST; mbox_call(8, MMU_DISABLE); - return (int)(mbox[5] & ~0xC0000000); + return (int)(mbox[5] & ~0xC0000000); } int bcm271x_notify_reboot(void) { - mbox[0] = 7 * 4; // length of the message + mbox[0] = 7*4; // length of the message mbox[1] = MBOX_REQUEST; // this is a request message mbox[2] = MBOX_TAG_NOTIFY_REBOOT; // (the tag id) mbox[3] = 0x00000004; // length + 4 mbox[4] = 0x00000000; // size of the data mbox[5] = 0x00000000; // request - mbox[6] = MBOX_TAG_LAST; + mbox[6] = MBOX_TAG_LAST; mbox_call(8, MMU_DISABLE); return 0; } int bcm271x_notify_xhci_reset(void) { - mbox[0] = 7 * 4; // length of the message + mbox[0] = 7*4; // length of the message mbox[1] = MBOX_REQUEST; // this is a request message mbox[2] = MBOX_TAG_NOTIFY_XHCI_RESET; // (the tag id) mbox[3] = 0x00000004; // length + 4 mbox[4] = 0x00000004; // size of the data mbox[5] = 0x00100000; // request - mbox[6] = MBOX_TAG_LAST; + mbox[6] = MBOX_TAG_LAST; mbox_call(8, MMU_DISABLE); return 0; } int bcm271x_gpu_enable(void) { - mbox[0] = 12 * 4; // length of the message + mbox[0] = 12*4; // length of the message mbox[1] = MBOX_REQUEST; // this is a request message - + mbox[2] = MBOX_TAG_CLOCK_SET_RATE; mbox[3] = 0x00000008; // (the tag id) mbox[4] = 0x00000008; // (the tag id) @@ -137,14 +116,14 @@ int bcm271x_gpu_enable(void) int bcm271x_mbox_hardware_get_model(void) { - mbox[0] = 8 * 4; // length of the message + mbox[0] = 8*4; // length of the message mbox[1] = MBOX_REQUEST; // this is a request message - + mbox[2] = MBOX_TAG_HARDWARE_GET_MODEL; mbox[3] = 4; // buffer size mbox[4] = 0; // len - mbox[5] = 0; + mbox[5] = 0; mbox[6] = 0; mbox[7] = MBOX_TAG_LAST; @@ -155,14 +134,14 @@ int bcm271x_mbox_hardware_get_model(void) int bcm271x_mbox_hardware_get_revison(void) { - mbox[0] = 8 * 4; // length of the message + mbox[0] = 8*4; // length of the message mbox[1] = MBOX_REQUEST; // this is a request message - - mbox[2] = MBOX_TAG_HARDWARE_GET_REV; + + mbox[2] = MBOX_TAG_HARDWARE_GET_REV; mbox[3] = 4; // buffer size mbox[4] = 0; // len - mbox[5] = 0; + mbox[5] = 0; mbox[6] = 0; mbox[7] = MBOX_TAG_LAST; @@ -171,22 +150,22 @@ int bcm271x_mbox_hardware_get_revison(void) return mbox[5]; } -int bcm271x_mbox_hardware_get_mac_address(uint8_t *mac) +int bcm271x_mbox_hardware_get_mac_address(uint8_t * mac) { - mbox[0] = 8 * 4; // length of the message + mbox[0] = 8*4; // length of the message mbox[1] = MBOX_REQUEST; // this is a request message - - mbox[2] = MBOX_TAG_HARDWARE_GET_MAC_ADDRESS; + + mbox[2] = MBOX_TAG_HARDWARE_GET_MAC_ADDRESS; mbox[3] = 6; // buffer size mbox[4] = 0; // len - mbox[5] = 0; + mbox[5] = 0; mbox[6] = 0; mbox[7] = MBOX_TAG_LAST; mbox_call(8, MMU_DISABLE); - char *mac_str = (char *)&mbox[5]; + char * mac_str = (char *)&mbox[5]; mac[0] = mac_str[0]; mac[1] = mac_str[1]; mac[2] = mac_str[2]; @@ -197,36 +176,36 @@ int bcm271x_mbox_hardware_get_mac_address(uint8_t *mac) } -int bcm271x_mbox_hardware_get_serial(rt_uint64_t *sn) +int bcm271x_mbox_hardware_get_serial(rt_uint64_t* sn) { - mbox[0] = 8 * 4; // length of the message + mbox[0] = 8*4; // length of the message mbox[1] = MBOX_REQUEST; // this is a request message - - mbox[2] = MBOX_TAG_HARDWARE_GET_SERIAL; + + mbox[2] = MBOX_TAG_HARDWARE_GET_SERIAL; mbox[3] = 8; // buffer size mbox[4] = 0; // len - mbox[5] = 0; + mbox[5] = 0; mbox[6] = 0; mbox[7] = MBOX_TAG_LAST; mbox_call(8, MMU_DISABLE); - sn = (rt_uint64_t *)&mbox[5]; + *sn = *(rt_uint64_t *)&mbox[5]; return 0; } -int bcm271x_mbox_hardware_get_arm_memory(rt_uint32_t *base, rt_uint32_t *size) +int bcm271x_mbox_hardware_get_arm_memory(rt_uint32_t * base, rt_uint32_t * size) { - mbox[0] = 8 * 4; // length of the message + mbox[0] = 8*4; // length of the message mbox[1] = MBOX_REQUEST; // this is a request message - - mbox[2] = MBOX_TAG_HARDWARE_GET_ARM_MEMORY; + + mbox[2] = MBOX_TAG_HARDWARE_GET_ARM_MEMORY; mbox[3] = 8; // buffer size mbox[4] = 0; // len - mbox[5] = 0; + mbox[5] = 0; mbox[6] = 0; mbox[7] = MBOX_TAG_LAST; @@ -234,21 +213,21 @@ int bcm271x_mbox_hardware_get_arm_memory(rt_uint32_t *base, rt_uint32_t *size) *base = mbox[5]; *size = mbox[6]; - + return 0; } -int bcm271x_mbox_hardware_get_vc_memory(rt_uint32_t *base, rt_uint32_t *size) +int bcm271x_mbox_hardware_get_vc_memory(rt_uint32_t * base, rt_uint32_t * size) { - mbox[0] = 8 * 4; // length of the message + mbox[0] = 8*4; // length of the message mbox[1] = MBOX_REQUEST; // this is a request message - + mbox[2] = MBOX_TAG_HARDWARE_GET_VC_MEMORY; mbox[3] = 8; // buffer size mbox[4] = 0; // len - mbox[5] = 0; + mbox[5] = 0; mbox[6] = 0; mbox[7] = MBOX_TAG_LAST; @@ -256,16 +235,16 @@ int bcm271x_mbox_hardware_get_vc_memory(rt_uint32_t *base, rt_uint32_t *size) *base = mbox[5]; *size = mbox[6]; - + return 0; } int bcm271x_mbox_clock_get_turbo(void) { - mbox[0] = 8 * 4; // length of the message + mbox[0] = 8*4; // length of the message mbox[1] = MBOX_REQUEST; // this is a request message - - mbox[2] = MBOX_TAG_CLOCK_GET_TURBO; + + mbox[2] = MBOX_TAG_CLOCK_GET_TURBO; mbox[3] = 8; // buffer size mbox[4] = 4; // len @@ -275,7 +254,7 @@ int bcm271x_mbox_clock_get_turbo(void) mbox[7] = MBOX_TAG_LAST; mbox_call(8, MMU_DISABLE); - if (mbox[5] != 0) + if(mbox[5] != 0) { return -1; } @@ -285,10 +264,10 @@ int bcm271x_mbox_clock_get_turbo(void) int bcm271x_mbox_clock_set_turbo(int level) { - mbox[0] = 8 * 4; // length of the message + mbox[0] = 8*4; // length of the message mbox[1] = MBOX_REQUEST; // this is a request message - - mbox[2] = MBOX_TAG_CLOCK_SET_TURBO; + + mbox[2] = MBOX_TAG_CLOCK_SET_TURBO; mbox[3] = 8; // buffer size mbox[4] = 8; // len @@ -298,7 +277,7 @@ int bcm271x_mbox_clock_set_turbo(int level) mbox[7] = MBOX_TAG_LAST; mbox_call(8, MMU_DISABLE); - if (mbox[5] != 0) + if(mbox[5] != 0) { return -1; } @@ -308,9 +287,9 @@ int bcm271x_mbox_clock_set_turbo(int level) int bcm271x_mbox_clock_get_state(int id) { - mbox[0] = 8 * 4; // length of the message + mbox[0] = 8*4; // length of the message mbox[1] = MBOX_REQUEST; // this is a request message - + mbox[2] = MBOX_TAG_CLOCK_GET_STATE; mbox[3] = 8; // buffer size mbox[4] = 4; // len @@ -321,7 +300,7 @@ int bcm271x_mbox_clock_get_state(int id) mbox[7] = MBOX_TAG_LAST; mbox_call(8, MMU_DISABLE); - if (mbox[5] != id) + if(mbox[5] != id) { return -1; } @@ -331,9 +310,9 @@ int bcm271x_mbox_clock_get_state(int id) int bcm271x_mbox_clock_set_state(int id, int state) { - mbox[0] = 8 * 4; // length of the message + mbox[0] = 8*4; // length of the message mbox[1] = MBOX_REQUEST; // this is a request message - + mbox[2] = MBOX_TAG_CLOCK_SET_STATE; mbox[3] = 8; // buffer size mbox[4] = 8; // len @@ -344,7 +323,7 @@ int bcm271x_mbox_clock_set_state(int id, int state) mbox[7] = MBOX_TAG_LAST; mbox_call(8, MMU_DISABLE); - if (mbox[5] != id) + if(mbox[5] != id) { return -1; } @@ -354,10 +333,10 @@ int bcm271x_mbox_clock_set_state(int id, int state) int bcm271x_mbox_clock_get_rate(int id) { - mbox[0] = 8 * 4; // length of the message + mbox[0] = 8*4; // length of the message mbox[1] = MBOX_REQUEST; // this is a request message - - mbox[2] = MBOX_TAG_CLOCK_GET_RATE; + + mbox[2] = MBOX_TAG_CLOCK_GET_RATE; mbox[3] = 8; // buffer size mbox[4] = 4; // len @@ -367,7 +346,7 @@ int bcm271x_mbox_clock_get_rate(int id) mbox[7] = MBOX_TAG_LAST; mbox_call(8, MMU_DISABLE); - if (mbox[5] != id) + if(mbox[5] != id) { return -1; } @@ -377,9 +356,9 @@ int bcm271x_mbox_clock_get_rate(int id) int bcm271x_mbox_clock_set_rate(int id, int rate) { - mbox[0] = 8 * 4; // length of the message + mbox[0] = 8*4; // length of the message mbox[1] = MBOX_REQUEST; // this is a request message - + mbox[2] = MBOX_TAG_CLOCK_SET_RATE; mbox[3] = 8; // buffer size mbox[4] = 8; // len @@ -390,7 +369,7 @@ int bcm271x_mbox_clock_set_rate(int id, int rate) mbox[7] = MBOX_TAG_LAST; mbox_call(8, MMU_DISABLE); - if (mbox[5] != id) + if(mbox[5] != id) { return -1; } @@ -400,9 +379,9 @@ int bcm271x_mbox_clock_set_rate(int id, int rate) int bcm271x_mbox_clock_get_max_rate(int id) { - mbox[0] = 8 * 4; // length of the message + mbox[0] = 8*4; // length of the message mbox[1] = MBOX_REQUEST; // this is a request message - + mbox[2] = MBOX_TAG_CLOCK_GET_MAX_RATE; mbox[3] = 8; // buffer size mbox[4] = 4; // len @@ -413,7 +392,7 @@ int bcm271x_mbox_clock_get_max_rate(int id) mbox[7] = MBOX_TAG_LAST; mbox_call(8, MMU_DISABLE); - if (mbox[5] != id) + if(mbox[5] != id) { return -1; } @@ -423,10 +402,10 @@ int bcm271x_mbox_clock_get_max_rate(int id) int bcm271x_mbox_clock_get_min_rate(int id) { - mbox[0] = 8 * 4; // length of the message + mbox[0] = 8*4; // length of the message mbox[1] = MBOX_REQUEST; // this is a request message - - mbox[2] = MBOX_TAG_CLOCK_GET_MIN_RATE; + + mbox[2] = MBOX_TAG_CLOCK_GET_MIN_RATE; mbox[3] = 8; // buffer size mbox[4] = 4; // len @@ -436,7 +415,7 @@ int bcm271x_mbox_clock_get_min_rate(int id) mbox[7] = MBOX_TAG_LAST; mbox_call(8, MMU_DISABLE); - if (mbox[5] != id) + if(mbox[5] != id) { return -1; } @@ -446,9 +425,9 @@ int bcm271x_mbox_clock_get_min_rate(int id) int bcm271x_mbox_power_get_state(int id) { - mbox[0] = 8 * 4; // length of the message + mbox[0] = 8*4; // length of the message mbox[1] = MBOX_REQUEST; // this is a request message - + mbox[2] = MBOX_TAG_POWER_GET_STATE; mbox[3] = 8; // buffer size mbox[4] = 4; // len @@ -459,7 +438,7 @@ int bcm271x_mbox_power_get_state(int id) mbox[7] = MBOX_TAG_LAST; mbox_call(8, MMU_DISABLE); - if (mbox[5] != id) + if(mbox[5] != id) { return -1; } @@ -469,9 +448,9 @@ int bcm271x_mbox_power_get_state(int id) int bcm271x_mbox_power_set_state(int id, int state) { - mbox[0] = 8 * 4; // length of the message + mbox[0] = 8*4; // length of the message mbox[1] = MBOX_REQUEST; // this is a request message - + mbox[2] = MBOX_TAG_POWER_SET_STATE; mbox[3] = 8; // buffer size mbox[4] = 8; // len @@ -482,7 +461,7 @@ int bcm271x_mbox_power_set_state(int id, int state) mbox[7] = MBOX_TAG_LAST; mbox_call(8, MMU_DISABLE); - if (mbox[5] != id) + if(mbox[5] != id) { return -1; } @@ -492,9 +471,9 @@ int bcm271x_mbox_power_set_state(int id, int state) int bcm271x_mbox_temp_get(void) { - mbox[0] = 8 * 4; // length of the message + mbox[0] = 8*4; // length of the message mbox[1] = MBOX_REQUEST; // this is a request message - + mbox[2] = MBOX_TAG_TEMP_GET; mbox[3] = 8; // buffer size mbox[4] = 4; // len @@ -505,7 +484,7 @@ int bcm271x_mbox_temp_get(void) mbox[7] = MBOX_TAG_LAST; mbox_call(8, MMU_DISABLE); - if (mbox[5] != 0) + if(mbox[5] != 0) { return -1; } @@ -515,9 +494,9 @@ int bcm271x_mbox_temp_get(void) int bcm271x_mbox_temp_get_max(void) { - mbox[0] = 8 * 4; // length of the message + mbox[0] = 8*4; // length of the message mbox[1] = MBOX_REQUEST; // this is a request message - + mbox[2] = MBOX_TAG_TEMP_GET_MAX; mbox[3] = 8; // buffer size mbox[4] = 4; // len @@ -528,7 +507,7 @@ int bcm271x_mbox_temp_get_max(void) mbox[7] = MBOX_TAG_LAST; mbox_call(8, MMU_DISABLE); - if (mbox[5] != 0) + if(mbox[5] != 0) { return -1; } diff --git a/bsp/raspberry-pi/raspi4-64/drivers/mbox.h b/bsp/raspberry-pi/raspi4-64/drivers/mbox.h new file mode 100644 index 0000000000..291cd77cf0 --- /dev/null +++ b/bsp/raspberry-pi/raspi4-64/drivers/mbox.h @@ -0,0 +1,180 @@ +/* + * Copyright (c) 2006-2023, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2020-09-10 bigmagic first version + */ + +#ifndef __MBOX_H__ +#define __MBOX_H__ + +#include + +//https://github.com/raspberrypi/firmware/wiki/Mailbox-property-interface +//https://github.com/hermanhermitage/videocoreiv + +/* a properly aligned buffer */ +extern volatile unsigned int* mbox; + +#define MBOX_REQUEST 0 + +/* channels */ +#define MBOX_CH_POWER 0 +#define MBOX_CH_FB 1 +#define MBOX_CH_VUART 2 +#define MBOX_CH_VCHIQ 3 +#define MBOX_CH_LEDS 4 +#define MBOX_CH_BTNS 5 +#define MBOX_CH_TOUCH 6 +#define MBOX_CH_COUNT 7 +#define MBOX_CH_PROP 8 + +/* tags */ +#define MBOX_TAG_SETPOWER 0x28001 +#define MBOX_TAG_SETCLKRATE 0x38002 +#define MBOX_GET_MAC_ADDRESS 0x10003 +#define MBOX_TAG_LAST 0 + +#define MMIO_BASE 0xFE000000 +#define VIDEOCORE_MBOX (MMIO_BASE+0x0000B880) +extern size_t videocore_mbox; +#define MBOX_READ ((volatile unsigned int*)(videocore_mbox+0x0)) +#define MBOX_POLL ((volatile unsigned int*)(videocore_mbox+0x10)) +#define MBOX_SENDER ((volatile unsigned int*)(videocore_mbox+0x14)) +#define MBOX_STATUS ((volatile unsigned int*)(videocore_mbox+0x18)) +#define MBOX_CONFIG ((volatile unsigned int*)(videocore_mbox+0x1C)) +#define MBOX_WRITE ((volatile unsigned int*)(videocore_mbox+0x20)) +#define MBOX_RESPONSE 0x80000000 +#define MBOX_FULL 0x80000000 +#define MBOX_EMPTY 0x40000000 + +#define DEVICE_ID_SD_CARD (0) +#define DEVICE_ID_USB_HCD (3) +#define POWER_STATE_OFF (0 << 0) +#define POWER_STATE_ON (1 << 0) +#define POWER_STATE_WAIT (1 << 1) +#define POWER_STATE_NO_DEVICE (1 << 1) // in response +#define MMU_ENABLE (1) +#define MMU_DISABLE (0) + +/* + * raspi hardware info + */ +enum { + MBOX_TAG_HARDWARE_GET_MODEL = 0x00010001, + MBOX_TAG_HARDWARE_GET_REV = 0x00010002, + MBOX_TAG_HARDWARE_GET_MAC_ADDRESS = 0x00010003, + MBOX_TAG_HARDWARE_GET_SERIAL = 0x00010004, + MBOX_TAG_HARDWARE_GET_ARM_MEMORY = 0x00010005, + MBOX_TAG_HARDWARE_GET_VC_MEMORY = 0x00010006, + MBOX_TAG_HARDWARE_GET_CLOCKS = 0x00010007, +}; + +/* + * raspi clock + */ +enum { + MBOX_TAG_CLOCK_GET_TURBO = 0x00030009, + MBOX_TAG_CLOCK_SET_TURBO = 0x00038009, + MBOX_TAG_CLOCK_GET_STATE = 0x00030001, + MBOX_TAG_CLOCK_SET_STATE = 0x00038001, + MBOX_TAG_CLOCK_GET_RATE = 0x00030002, + MBOX_TAG_CLOCK_SET_RATE = 0x00038002, + MBOX_TAG_CLOCK_GET_MAX_RATE = 0x00030004, + MBOX_TAG_CLOCK_GET_MIN_RATE = 0x00030007, +}; + +/* + * raspi power + */ +enum { + MBOX_TAG_POWER_GET_STATE = 0x00020001, + MBOX_TAG_POWER_SET_STATE = 0x00028001, +}; + +/* + * raspi temperature + */ +enum { + MBOX_TAG_TEMP_GET = 0x00030006, + MBOX_TAG_TEMP_GET_MAX = 0x0003000A, +}; + +/* + * raspi Memory + */ +enum { + MBOX_TAG_ALLOCATE_MEMORY = 0x0003000C, // Memory: Allocates Contiguous Memory On The GPU (Response: Handle) + MBOX_TAG_LOCK_MEMORY = 0x0003000D, // Memory: Unlock Buffer (Response: Status) + MBOX_TAG_UNLOCK_MEMORY = 0x0003000E, // Memory: Unlock Buffer (Response: Status) + MBOX_TAG_RELEASE_MEMORY = 0x0003000F, // Memory: Free The Memory Buffer (Response: Status) + MBOX_TAG_EXECUTE_CODE = 0x00030010, // Memory: Calls The Function At Given (Bus) Address And With Arguments Given +}; + +/* + * raspi GPU + */ +enum { + MBOX_TAG_EXECUTE_QPU = 0x00030011, // QPU: Calls The QPU Function At Given (Bus) Address And With Arguments Given (Response: Number Of QPUs, Control, No Flush, Timeout In ms) + MBOX_TAG_ENABLE_QPU = 0x00030012, // QPU: Enables The QPU (Response: Enable State) +}; + +/* + * raspi HDMI + */ +#define MBOX_TAG_GET_EDID_BLOCK 0x00030020 // HDMI: Read Specificed EDID Block From Attached HDMI/DVI Device (Response: Block Number, Status, EDID Block (128 Bytes)) + +/* + * raspi NOTIFY + */ +#define MBOX_TAG_NOTIFY_REBOOT 0x00030048 +#define MBOX_TAG_NOTIFY_XHCI_RESET 0x00030058 + +/* +* touch +*/ +#define MBOX_TAG_GET_TOUCHBUF (0x0004000F) + +#define MBOX_ADDR 0x08000000 +extern size_t mbox_addr; + +#define RES_CLK_ID (0x000000000) +#define EMMC_CLK_ID (0x000000001) +#define UART_CLK_ID (0x000000002) +#define ARM_CLK_ID (0x000000003) +#define CORE_CLK_ID (0x000000004) +#define V3D_CLK_ID (0x000000005) +#define H264_CLK_ID (0x000000006) +#define ISP_CLK_ID (0x000000007) +#define SDRAM_CLK_ID (0x000000008) +#define PIXEL_CLK_ID (0x000000009) +#define PWM_CLK_ID (0x00000000a) + +int mbox_call(unsigned char ch, int mmu_enable); +int bcm271x_mbox_get_touch(void); +int bcm271x_notify_reboot(void); +int bcm271x_notify_xhci_reset(void); +int bcm271x_gpu_enable(void); +int bcm271x_mbox_hardware_get_model(void); +int bcm271x_mbox_hardware_get_revison(void); +int bcm271x_mbox_hardware_get_mac_address(uint8_t * mac); +int bcm271x_mbox_hardware_get_serial(rt_uint64_t* sn); +int bcm271x_mbox_hardware_get_arm_memory(rt_uint32_t * base, rt_uint32_t * size); +int bcm271x_mbox_hardware_get_vc_memory(rt_uint32_t * base, rt_uint32_t * size); +int bcm271x_mbox_clock_get_turbo(void); +int bcm271x_mbox_clock_set_turbo(int level); +int bcm271x_mbox_clock_get_state(int id); +int bcm271x_mbox_clock_set_state(int id, int state); +int bcm271x_mbox_clock_get_rate(int id); +int bcm271x_mbox_clock_set_rate(int id, int rate); +int bcm271x_mbox_clock_get_max_rate(int id); +int bcm271x_mbox_clock_get_min_rate(int id); +int bcm271x_mbox_power_get_state(int id); +int bcm271x_mbox_power_set_state(int id, int state); +int bcm271x_mbox_temp_get(void); +int bcm271x_mbox_temp_get_max(void); + +#endif diff --git a/bsp/raspberry-pi/raspi4-64/drivers/raspi4.h b/bsp/raspberry-pi/raspi4-64/drivers/raspi4.h new file mode 100644 index 0000000000..64b40d3753 --- /dev/null +++ b/bsp/raspberry-pi/raspi4-64/drivers/raspi4.h @@ -0,0 +1,200 @@ +/* + * Copyright (c) 2006-2023, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2023-02-06 RT-Thread first version + */ +#ifndef __RASPI4_H__ +#define __RASPI4_H__ + +#include + +//https://www.raspberrypi.org/documentation/hardware/raspberrypi/bcm2711/rpi_DATA_2711_1p0.pdf + +#define __REG32(x) (*((volatile unsigned int *)(x))) +#define __REG16(x) (*((volatile unsigned short *)(x))) + +/* GIC IRQ MAX */ +#define MAX_HANDLERS (256) + +/* base address */ +#define PER_BASE (0xFE000000) + +//gpio offset +#define GPIO_BASE_OFFSET (0x00200000) + + +#define PL011_UART_BASE_OFFSET (0x00201000) +//pl011 offset +#define PL011_UART0_BASE_OFFSET (0x00201000) +#define PL011_UART2_BASE_OFFSET (0x00201400) +#define PL011_UART3_BASE_OFFSET (0x00201600) +#define PL011_UART4_BASE_OFFSET (0x00201800) +#define PL011_UART5_BASE_OFFSET (0x00201A00) + +//pactl cs offset +#define PACTL_CS_OFFSET (0x00204E00) + +//aux offset +#define AUX_BASE_OFFSET (0x00215000) + +/* GPIO */ +#define GPIO_BASE_ADDR (PER_BASE + GPIO_BASE_OFFSET) +extern size_t gpio_base_addr; +#define GPIO_BASE (gpio_base_addr) +#define GPIO_IRQ_NUM (3) //40 pin mode +#define IRQ_GPIO0 (96 + 49) //bank0 (0 to 27) +#define IRQ_GPIO1 (96 + 50) //bank1 (28 to 45) +#define IRQ_GPIO2 (96 + 51) //bank2 (46 to 57) +#define IRQ_GPIO3 (96 + 52) //bank3 + +/* Timer (ARM side) */ +#define ARM_TIMER_IRQ (64) +extern size_t arm_timer_base; +#define ARM_TIMER_BASE (PER_BASE + 0xB000) +#define ARM_TIMER_LOAD HWREG32(arm_timer_base + 0x400) +#define ARM_TIMER_VALUE HWREG32(arm_timer_base + 0x404) +#define ARM_TIMER_CTRL HWREG32(arm_timer_base + 0x408) +#define ARM_TIMER_IRQCLR HWREG32(arm_timer_base + 0x40C) +#define ARM_TIMER_RAWIRQ HWREG32(arm_timer_base + 0x410) +#define ARM_TIMER_MASKIRQ HWREG32(arm_timer_base + 0x414) +#define ARM_TIMER_RELOAD HWREG32(arm_timer_base + 0x418) +#define ARM_TIMER_PREDIV HWREG32(arm_timer_base + 0x41C) +#define ARM_TIMER_CNTR HWREG32(arm_timer_base + 0x420) + +/* UART PL011 */ +#define UART_BASE (PER_BASE + PL011_UART_BASE_OFFSET) +//extern uint32_t uart_base_addr; +#define UART0_BASE (UART_BASE + 0x0) +#define UART2_BASE (UART_BASE + 0x400) +#define UART3_BASE (UART_BASE + 0x600) +#define UART4_BASE (UART_BASE + 0x800) +#define UART5_BASE (UART_BASE + 0xA00) +#define IRQ_AUX_UART (96 + 29) +#define UART_REFERENCE_CLOCK (48000000) + +/* AUX */ +//#define AUX_BASE_ADDR (PER_BASE + AUX_BASE_OFFSET) +//extern uint32_t aux_addr; +//#define AUX_BASE (aux_addr + 0x0) + +#define AUX_BASE (PER_BASE + AUX_BASE_OFFSET) +#define IRQ_PL011 (96 + 57) + +/* Peripheral IRQ OR-ing */ +#define PACTL_CS_ADDR (PER_BASE + PACTL_CS_OFFSET) +extern size_t pactl_cs_base; +#define PACTL_CS HWREG32(pactl_cs_base) +typedef enum +{ + IRQ_SPI0 = 0x00000000, + IRQ_SPI1 = 0x00000002, + IRQ_SPI2 = 0x00000004, + IRQ_SPI3 = 0x00000008, + IRQ_SPI4 = 0x00000010, + IRQ_SPI5 = 0x00000020, + IRQ_SPI6 = 0x00000040, + IRQ_I2C0 = 0x00000100, + IRQ_I2C1 = 0x00000200, + IRQ_I2C2 = 0x00000400, + IRQ_I2C3 = 0x00000800, + IRQ_I2C4 = 0x00001000, + IRQ_I2C5 = 0x00002000, + IRQ_I2C6 = 0x00004000, + IRQ_I2C7 = 0x00008000, + IRQ_UART5 = 0x00010000, + IRQ_UART4 = 0x00020000, + IRQ_UART3 = 0x00040000, + IRQ_UART2 = 0x00080000, + IRQ_UART0 = 0x00100000 +} PACTL_CS_VAL; + +// 0x40, 0x44, 0x48, 0x4c: Core 0~3 Timers interrupt control +#define CORE0_TIMER_IRQ_CTRL HWREG32(0xFF800040) +#define TIMER_IRQ 30 +#define NON_SECURE_TIMER_IRQ (1 << 1) + +/* GIC */ +#define INTC_BASE (0xff800000) +#define ARM_GIC_NR_IRQS (512) +#define ARM_GIC_MAX_NR (512) +#define GIC_V2_BASE (INTC_BASE + 0x00040000) +extern size_t gic_base_addr; +#define GIC_V2_DISTRIBUTOR_BASE (gic_base_addr + 0x1000) +#define GIC_V2_CPU_INTERFACE_BASE (gic_base_addr + 0x2000) +#define GIC_V2_HYPERVISOR_BASE (gic_base_addr + 0x4000) +#define GIC_V2_VIRTUAL_CPU_BASE (gic_base_addr + 0x6000) + +#define GIC_PL400_DISTRIBUTOR_PPTR GIC_V2_DISTRIBUTOR_BASE +#define GIC_PL400_CONTROLLER_PPTR GIC_V2_CPU_INTERFACE_BASE + +#define GIC_IRQ_START 0 + +#define GIC_ACK_INTID_MASK 0x000003ff + + +//watchdog +#define WDT_BASE (PER_BASE + 0x00100000) +extern size_t wdt_base_addr; +#define PM_RSTC HWREG32(wdt_base_addr + 0x1c) +#define PM_RSTS HWREG32(wdt_base_addr + 0x20) +#define PM_WDOG HWREG32(wdt_base_addr + 0x24) + +#define PM_PASSWORD (0x5A000000) +#define PM_WDOG_TIME_SET (0x000fffff) +#define PM_RSTS_HADWRH_SET (0x00000040) +#define PM_RSTC_WRCFG_FULL_RESET (0x00000020) +#define PM_RSTC_WRCFG_CLR (0xffffffcf) +#define PM_RSTC_RESET (0x00000102) + +//timer +#define ST_BASE_OFFSET (0x003000) +#define STIMER_BASE (PER_BASE + ST_BASE_OFFSET) +extern size_t stimer_base_addr; +#define STIMER_CS __REG32(stimer_base_addr + 0x0000) +#define STIMER_CLO __REG32(stimer_base_addr + 0x0004) +#define STIMER_CHI __REG32(stimer_base_addr + 0x0008) +#define STIMER_C0 __REG32(stimer_base_addr + 0x000C) +#define STIMER_C1 __REG32(stimer_base_addr + 0x0010) +#define STIMER_C2 __REG32(stimer_base_addr + 0x0014) +#define STIMER_C3 __REG32(stimer_base_addr + 0x0018) + +#define DELAY_MICROS(micros) \ + do{ \ + rt_uint32_t compare = STIMER_CLO + micros * 25; \ + while (STIMER_CLO < compare); \ + } while (0) + +//External Mass Media Controller (SD Card) +#define MMC0_BASE_ADDR (PER_BASE+0x300000) +extern size_t mmc0_base_addr; +#define MMC2_BASE_ADDR (PER_BASE+0x340000) +extern size_t mmc2_base_addr; + +//mac +#define MAC_REG (void *)(0xfd580000) +extern uint8_t * mac_reg_base_addr; + +#define ETH_IRQ (160+29) + +#define SEND_DATA_NO_CACHE (0x08200000) +extern uint8_t * eth_send_no_cache; + +#define RECV_DATA_NO_CACHE (0x08400000) +extern uint8_t * eth_recv_no_cache; + +/* the basic constants and interfaces needed by gic */ +rt_inline size_t platform_get_gic_dist_base(void) +{ + return GIC_PL400_DISTRIBUTOR_PPTR; +} + +rt_inline size_t platform_get_gic_cpu_base(void) +{ + return GIC_PL400_CONTROLLER_PPTR; +} + +#endif diff --git a/bsp/raspberry-pi/raspi4-64/link.lds b/bsp/raspberry-pi/raspi4-64/link.lds index 953be4c28b..b859ddefe7 100644 --- a/bsp/raspberry-pi/raspi4-64/link.lds +++ b/bsp/raspberry-pi/raspi4-64/link.lds @@ -1,85 +1,66 @@ -/* - * Copyright (c) 2006-2023, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * 2017-5-30 bernard first version - */ - -/* _EL1_STACK_SIZE = DEFINED(_EL1_STACK_SIZE) ? _EL1_STACK_SIZE : 0x20000; */ - +OUTPUT_FORMAT("elf64-littleaarch64", "elf64-littleaarch64", "elf64-littleaarch64") +OUTPUT_ARCH(aarch64) SECTIONS { - . = 0x80000; - . = ALIGN(4096); + . = 0x208000; + /* . = 0xffff000000008000; */ + + __text_start = .; .text : { - KEEP(*(.text.entrypoint)) /* The entry point */ - *(.vectors) - *(.text) /* remaining code */ - *(.text.*) /* remaining code */ + KEEP(*(.text.entrypoint)) + KEEP(*(.vectors)) + *(.text) + *(.text.*) - *(.rodata) /* read-only data (constants) */ - *(.rodata*) - *(.glue_7) - *(.glue_7t) - *(.gnu.linkonce.t*) - - *(COMMON) + /* section information for utest */ + . = ALIGN(4); + __rt_utest_tc_tab_start = .; + KEEP(*(UtestTcTab)) + __rt_utest_tc_tab_end = .; /* section information for finsh shell */ - . = ALIGN(16); + . = ALIGN(4); __fsymtab_start = .; KEEP(*(FSymTab)) __fsymtab_end = .; - . = ALIGN(16); + . = ALIGN(4); __vsymtab_start = .; KEEP(*(VSymTab)) __vsymtab_end = .; - . = ALIGN(16); + . = ALIGN(4); - /* section information for initial. */ - . = ALIGN(16); + /* section information for modules */ + . = ALIGN(4); + __rtmsymtab_start = .; + KEEP(*(RTMSymTab)) + __rtmsymtab_end = .; + + /* section information for initialization */ + . = ALIGN(4); __rt_init_start = .; KEEP(*(SORT(.rti_fn*))) __rt_init_end = .; - . = ALIGN(16); + } =0 + __text_end = .; - . = ALIGN(16); - _etext = .; - } - - .eh_frame_hdr : + .ARM.exidx : { - *(.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.*) + __exidx_start = .; + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + __exidx_end = .; } - . = ALIGN(16); + __rodata_start = .; + .rodata : { *(.rodata) *(.rodata.*) } + __rodata_end = .; + + . = ALIGN(4); .ctors : { PROVIDE(__ctors_start__ = .); - /* new GCC version uses .init_array */ - KEEP(*(SORT(.init_array.*))) - KEEP(*(.init_array)) + KEEP(*(SORT(.ctors.*))) + KEEP(*(.ctors)) PROVIDE(__ctors_end__ = .); } @@ -91,51 +72,38 @@ SECTIONS PROVIDE(__dtors_end__ = .); } - . = ALIGN(16); - .bss : + . = ALIGN(8); + __data_start = .; + .data : { - PROVIDE(__bss_start = .); - *(.bss) - *(.bss.*) - *(.dynbss) - - PROVIDE(__bss_end = .); + *(.data) + *(.data.*) } - _end = .; + __data_end = .; + + . = ALIGN(8); + __bss_start = .; + .bss : + { + *(.bss) + *(.bss.*) + *(COMMON) + . = ALIGN(4); + } + . = ALIGN(4); + __bss_end = .; /* Stabs debugging sections. */ - .stab 0 : { *(.stab) } - .stabstr 0 : { *(.stabstr) } - .stab.excl 0 : { *(.stab.excl) } - .stab.exclstr 0 : { *(.stab.exclstr) } - .stab.index 0 : { *(.stab.index) } + .stab 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) } -} + .comment 0 : { *(.comment) } -__bss_size = SIZEOF(.bss); + __data_size = SIZEOF(.data); + __bss_size = SIZEOF(.bss); + + _end = .; +} diff --git a/bsp/raspberry-pi/raspi4-64/link_smart.lds b/bsp/raspberry-pi/raspi4-64/link_smart.lds new file mode 100644 index 0000000000..435053f891 --- /dev/null +++ b/bsp/raspberry-pi/raspi4-64/link_smart.lds @@ -0,0 +1,109 @@ +OUTPUT_FORMAT("elf64-littleaarch64", "elf64-littleaarch64", "elf64-littleaarch64") +OUTPUT_ARCH(aarch64) +SECTIONS +{ + /* . = 0x208000; */ + . = 0xffff000000008000; + + __text_start = .; + .text : + { + KEEP(*(.text.entrypoint)) + KEEP(*(.vectors)) + *(.text) + *(.text.*) + + /* section information for utest */ + . = ALIGN(4); + __rt_utest_tc_tab_start = .; + KEEP(*(UtestTcTab)) + __rt_utest_tc_tab_end = .; + + /* section information for finsh shell */ + . = ALIGN(4); + __fsymtab_start = .; + KEEP(*(FSymTab)) + __fsymtab_end = .; + . = ALIGN(4); + __vsymtab_start = .; + KEEP(*(VSymTab)) + __vsymtab_end = .; + . = ALIGN(4); + + /* section information for modules */ + . = ALIGN(4); + __rtmsymtab_start = .; + KEEP(*(RTMSymTab)) + __rtmsymtab_end = .; + + /* section information for initialization */ + . = ALIGN(4); + __rt_init_start = .; + KEEP(*(SORT(.rti_fn*))) + __rt_init_end = .; + } =0 + __text_end = .; + + .ARM.exidx : + { + __exidx_start = .; + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + __exidx_end = .; + } + + __rodata_start = .; + .rodata : { *(.rodata) *(.rodata.*) } + __rodata_end = .; + + . = 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(8); + __data_start = .; + .data : + { + *(.data) + *(.data.*) + } + __data_end = .; + + . = ALIGN(8); + __bss_start = .; + .bss : + { + *(.bss) + *(.bss.*) + *(COMMON) + . = ALIGN(4); + } + . = ALIGN(4); + __bss_end = .; + + /* Stabs debugging sections. */ + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + + __data_size = SIZEOF(.data); + __bss_size = SIZEOF(.bss); + + _end = .; +} diff --git a/bsp/raspberry-pi/raspi4-64/rtconfig.h b/bsp/raspberry-pi/raspi4-64/rtconfig.h index a6730349d4..ff4b54bd7e 100644 --- a/bsp/raspberry-pi/raspi4-64/rtconfig.h +++ b/bsp/raspberry-pi/raspi4-64/rtconfig.h @@ -7,24 +7,29 @@ /* RT-Thread Kernel */ #define RT_NAME_MAX 8 -#define RT_ALIGN_SIZE 8 +#define RT_USING_SMP +#define RT_CPUS_NR 4 +#define RT_ALIGN_SIZE 4 #define RT_THREAD_PRIORITY_32 #define RT_THREAD_PRIORITY_MAX 32 -#define RT_TICK_PER_SECOND 100 +#define RT_TICK_PER_SECOND 1000 #define RT_USING_OVERFLOW_CHECK #define RT_USING_HOOK #define RT_HOOK_USING_FUNC_PTR #define RT_USING_IDLE_HOOK #define RT_IDLE_HOOK_LIST_SIZE 4 -#define IDLE_THREAD_STACK_SIZE 4096 +#define IDLE_THREAD_STACK_SIZE 8192 +#define SYSTEM_THREAD_STACK_SIZE 8192 #define RT_USING_TIMER_SOFT #define RT_TIMER_THREAD_PRIO 4 -#define RT_TIMER_THREAD_STACK_SIZE 4096 +#define RT_TIMER_THREAD_STACK_SIZE 8192 /* kservice optimization */ +#define RT_KSERVICE_USING_STDLIB #define RT_KPRINTF_USING_LONGLONG #define RT_DEBUG +#define RT_DEBUG_COLOR /* Inter-Thread communication */ @@ -37,20 +42,21 @@ /* Memory Management */ #define RT_PAGE_MAX_ORDER 11 -#define RT_USING_MEMPOOL -#define RT_USING_SMALL_MEM -#define RT_USING_SMALL_MEM_AS_HEAP +#define RT_USING_SLAB +#define RT_USING_SLAB_AS_HEAP #define RT_USING_HEAP /* Kernel Device Object */ #define RT_USING_DEVICE +#define RT_USING_INTERRUPT_INFO #define RT_USING_CONSOLE -#define RT_CONSOLEBUF_SIZE 128 +#define RT_CONSOLEBUF_SIZE 256 #define RT_CONSOLE_DEVICE_NAME "uart0" #define RT_VER_NUM 0x50000 #define ARCH_CPU_64BIT #define RT_USING_CACHE +#define RT_USING_HW_ATOMIC #define ARCH_MM_MMU #define ARCH_ARM #define ARCH_ARM_MMU @@ -60,14 +66,14 @@ #define RT_USING_COMPONENTS_INIT #define RT_USING_USER_MAIN -#define RT_MAIN_THREAD_STACK_SIZE 4096 +#define RT_MAIN_THREAD_STACK_SIZE 8192 #define RT_MAIN_THREAD_PRIORITY 10 #define RT_USING_MSH #define RT_USING_FINSH #define FINSH_USING_MSH #define FINSH_THREAD_NAME "tshell" #define FINSH_THREAD_PRIORITY 20 -#define FINSH_THREAD_STACK_SIZE 4096 +#define FINSH_THREAD_STACK_SIZE 8192 #define FINSH_USING_HISTORY #define FINSH_HISTORY_LINES 5 #define FINSH_USING_SYMTAB @@ -78,9 +84,9 @@ #define RT_USING_DFS #define DFS_USING_POSIX #define DFS_USING_WORKDIR -#define DFS_FILESYSTEMS_MAX 2 -#define DFS_FILESYSTEM_TYPES_MAX 2 -#define DFS_FD_MAX 16 +#define DFS_FILESYSTEMS_MAX 4 +#define DFS_FILESYSTEM_TYPES_MAX 4 +#define DFS_FD_MAX 32 #define RT_USING_DFS_ELMFAT /* elm-chan's FatFs, Generic FAT Filesystem Module */ @@ -97,6 +103,7 @@ #define RT_DFS_ELM_REENTRANT #define RT_DFS_ELM_MUTEX_TIMEOUT 3000 #define RT_USING_DFS_DEVFS +#define RT_USING_DFS_TMPFS /* Device Drivers */ @@ -109,16 +116,26 @@ #define RT_USING_SERIAL_V1 #define RT_SERIAL_USING_DMA #define RT_SERIAL_RB_BUFSZ 64 +#define RT_USING_HWTIMER +#define RT_USING_I2C +#define RT_USING_I2C_BITOPS #define RT_USING_PIN +#define RT_USING_NULL +#define RT_USING_ZERO +#define RT_USING_RANDOM #define RT_USING_RTC -#define RT_USING_ALARM +#define RT_USING_SOFT_RTC #define RT_USING_SDIO -#define RT_SDIO_STACK_SIZE 512 +#define RT_SDIO_STACK_SIZE 8192 #define RT_SDIO_THREAD_PRIORITY 15 #define RT_MMCSD_STACK_SIZE 8192 #define RT_MMCSD_THREAD_PREORITY 22 #define RT_MMCSD_MAX_PARTITION 16 +#define RT_USING_SPI #define RT_USING_WDT +#define RT_USING_TOUCH +#define RT_USING_LCD +#define RT_USING_DEV_BUS /* Using USB */ @@ -129,6 +146,13 @@ /* POSIX (Portable Operating System Interface) layer */ +#define RT_USING_POSIX_FS +#define RT_USING_POSIX_DEVIO +#define RT_USING_POSIX_STDIO +#define RT_USING_POSIX_TERMIOS +#define RT_USING_POSIX_DELAY +#define RT_USING_POSIX_CLOCK +#define RT_USING_POSIX_TIMER /* Interprocess Communication (IPC) */ @@ -153,8 +177,8 @@ #define NETDEV_IPV4 1 #define NETDEV_IPV6 0 #define RT_USING_LWIP -#define RT_USING_LWIP203 -#define RT_USING_LWIP_VER_NUM 0x20003 +#define RT_USING_LWIP212 +#define RT_USING_LWIP_VER_NUM 0x20102 #define RT_LWIP_MEM_ALIGNMENT 4 #define RT_LWIP_IGMP #define RT_LWIP_ICMP @@ -165,26 +189,27 @@ /* Static IPv4 Address */ -#define RT_LWIP_IPADDR "192.168.1.30" -#define RT_LWIP_GWADDR "192.168.1.1" +#define RT_LWIP_IPADDR "192.168.137.100" +#define RT_LWIP_GWADDR "192.168.137.1" #define RT_LWIP_MSKADDR "255.255.255.0" #define RT_LWIP_UDP #define RT_LWIP_TCP #define RT_LWIP_RAW -#define RT_MEMP_NUM_NETCONN 8 +#define RT_MEMP_NUM_NETCONN 16 #define RT_LWIP_PBUF_NUM 16 #define RT_LWIP_RAW_PCB_NUM 4 -#define RT_LWIP_UDP_PCB_NUM 4 -#define RT_LWIP_TCP_PCB_NUM 4 +#define RT_LWIP_UDP_PCB_NUM 8 +#define RT_LWIP_TCP_PCB_NUM 8 #define RT_LWIP_TCP_SEG_NUM 40 -#define RT_LWIP_TCP_SND_BUF 8196 -#define RT_LWIP_TCP_WND 8196 +#define RT_LWIP_TCP_SND_BUF 8192 +#define RT_LWIP_TCP_WND 8192 #define RT_LWIP_TCPTHREAD_PRIORITY 10 #define RT_LWIP_TCPTHREAD_MBOX_SIZE 8 -#define RT_LWIP_TCPTHREAD_STACKSIZE 4096 +#define RT_LWIP_TCPTHREAD_STACKSIZE 16384 #define RT_LWIP_ETHTHREAD_PRIORITY 12 -#define RT_LWIP_ETHTHREAD_STACKSIZE 4096 +#define RT_LWIP_ETHTHREAD_STACKSIZE 16384 #define RT_LWIP_ETHTHREAD_MBOX_SIZE 8 +#define RT_LWIP_REASSEMBLY_FRAG #define LWIP_NETIF_STATUS_CALLBACK 1 #define LWIP_NETIF_LINK_CALLBACK 1 #define SO_REUSE 1 @@ -192,13 +217,15 @@ #define LWIP_SO_SNDTIMEO 1 #define LWIP_SO_RCVBUF 1 #define LWIP_SO_LINGER 0 -#define LWIP_NETIF_LOOPBACK 0 +#define RT_LWIP_NETIF_LOOPBACK +#define LWIP_NETIF_LOOPBACK 1 #define RT_LWIP_USING_PING /* Utilities */ -#define RT_USING_RYM -#define YMODEM_USING_FILE_TRANSFER +#define RT_USING_UTEST +#define UTEST_THR_STACK_SIZE 8192 +#define UTEST_THR_PRIORITY 20 #define RT_USING_ADT /* RT-Thread Utestcases */ @@ -261,11 +288,6 @@ /* peripheral libraries and drivers */ -/* sensors drivers */ - - -/* touch drivers */ - /* Kendryte SDK */ @@ -273,9 +295,6 @@ /* AI packages */ -/* Signal Processing and Control Algorithm Packages */ - - /* miscellaneous packages */ /* project laboratory */ @@ -319,15 +338,8 @@ /* Uncategorized */ -/* Privated Packages of RealThread */ - - -/* Network Utilities */ - - -/* RT-Thread Smart */ - #define BCM2711_SOC +#define BSP_SUPPORT_FPU /* Hardware Drivers Config */ @@ -335,17 +347,18 @@ #define BSP_USING_UART #define RT_USING_UART0 +#define RT_USING_UART3 +#define RT_USING_UART4 #define BSP_USING_GIC #define BSP_USING_GICV2 #define BSP_USING_PIN #define BSP_USING_CORETIMER #define BSP_USING_WDT -#define BSP_USING_RTC -#define BSP_USING_ALARM #define BSP_USING_SDIO #define BSP_USING_SDIO0 /* Board Peripheral Drivers */ +#define BSP_USING_HDMI #endif diff --git a/bsp/raspberry-pi/raspi4-64/rtconfig.py b/bsp/raspberry-pi/raspi4-64/rtconfig.py index 2e163e05ba..ded95340fc 100644 --- a/bsp/raspberry-pi/raspi4-64/rtconfig.py +++ b/bsp/raspberry-pi/raspi4-64/rtconfig.py @@ -35,15 +35,15 @@ if PLATFORM == 'gcc': OBJCPY = PREFIX + 'objcopy' DEVICE = ' -march=armv8-a -mtune=cortex-a72' - CFLAGS = DEVICE + ' -Wall -Wno-cpp' + CFLAGS = DEVICE + ' -Wall -Wno-cpp -D_POSIX_SOURCE' 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' + CFLAGS += ' -O0 -ggdb' + AFLAGS += ' -ggdb' else: CFLAGS += ' -O2' diff --git a/bsp/raspberry-pi/raspi4-64/tools/config.txt b/bsp/raspberry-pi/raspi4-64/tools/config.txt new file mode 100644 index 0000000000..84ce211fad --- /dev/null +++ b/bsp/raspberry-pi/raspi4-64/tools/config.txt @@ -0,0 +1,5 @@ +enable_uart=1 +kernel=u-boot64.bin +#kernel=kernel7.img +#kernel_address=0xc0000000 +arm_64bit=1 diff --git a/bsp/raspberry-pi/raspi4-64/tools/u-boot64.bin b/bsp/raspberry-pi/raspi4-64/tools/u-boot64.bin new file mode 100644 index 0000000000000000000000000000000000000000..ae3bfc7153755adb6b5a9791d249b19d5d0d6282 GIT binary patch literal 516040 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

_J7D0&3bN3&#%6*Y{tNDzWT8QivXW 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 z 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 literal 0 HcmV?d00001