修改部分格式问题

[add] 增加ft2004 BSP
This commit is contained in:
huanghe 2021-05-21 18:43:59 +08:00 committed by huanghe
parent 17cae02ad5
commit 0c5692eece
131 changed files with 17377 additions and 0 deletions

726
bsp/ft2004/.config Normal file
View File

@ -0,0 +1,726 @@
#
# Automatically generated file; DO NOT EDIT.
# RT-Thread Project Configuration
#
#
# RT-Thread Kernel
#
CONFIG_RT_NAME_MAX=32
# CONFIG_RT_USING_ARCH_DATA_TYPE is not set
CONFIG_RT_USING_SMP=y
CONFIG_RT_CPUS_NR=4
CONFIG_RT_ALIGN_SIZE=128
# CONFIG_RT_THREAD_PRIORITY_8 is not set
CONFIG_RT_THREAD_PRIORITY_32=y
# CONFIG_RT_THREAD_PRIORITY_256 is not set
CONFIG_RT_THREAD_PRIORITY_MAX=32
CONFIG_RT_TICK_PER_SECOND=100
CONFIG_RT_USING_OVERFLOW_CHECK=y
CONFIG_RT_USING_HOOK=y
CONFIG_RT_USING_IDLE_HOOK=y
CONFIG_RT_IDLE_HOOK_LIST_SIZE=4
CONFIG_IDLE_THREAD_STACK_SIZE=4096
CONFIG_RT_USING_TIMER_SOFT=y
CONFIG_RT_TIMER_THREAD_PRIO=4
CONFIG_RT_TIMER_THREAD_STACK_SIZE=512
#
# kservice optimization
#
# CONFIG_RT_KSERVICE_USING_STDLIB is not set
# CONFIG_RT_KSERVICE_USING_TINY_SIZE is not set
CONFIG_RT_DEBUG=y
CONFIG_RT_DEBUG_COLOR=y
# CONFIG_RT_DEBUG_INIT_CONFIG is not set
# CONFIG_RT_DEBUG_THREAD_CONFIG is not set
# CONFIG_RT_DEBUG_SCHEDULER_CONFIG is not set
# CONFIG_RT_DEBUG_IPC_CONFIG is not set
# CONFIG_RT_DEBUG_TIMER_CONFIG is not set
# CONFIG_RT_DEBUG_IRQ_CONFIG is not set
# CONFIG_RT_DEBUG_MEM_CONFIG is not set
# CONFIG_RT_DEBUG_SLAB_CONFIG is not set
# CONFIG_RT_DEBUG_MEMHEAP_CONFIG is not set
# CONFIG_RT_DEBUG_MODULE_CONFIG is not set
#
# Inter-Thread communication
#
CONFIG_RT_USING_SEMAPHORE=y
CONFIG_RT_USING_MUTEX=y
CONFIG_RT_USING_EVENT=y
CONFIG_RT_USING_MAILBOX=y
CONFIG_RT_USING_MESSAGEQUEUE=y
# CONFIG_RT_USING_SIGNALS is not set
#
# Memory Management
#
# CONFIG_RT_USING_MEMPOOL is not set
CONFIG_RT_USING_MEMHEAP=y
# CONFIG_RT_USING_NOHEAP is not set
# CONFIG_RT_USING_SMALL_MEM is not set
CONFIG_RT_USING_SLAB=y
# CONFIG_RT_USING_MEMHEAP_AS_HEAP is not set
# CONFIG_RT_USING_USERHEAP is not set
# CONFIG_RT_USING_MEMTRACE is not set
CONFIG_RT_USING_HEAP=y
#
# Kernel Device Object
#
CONFIG_RT_USING_DEVICE=y
# CONFIG_RT_USING_DEVICE_OPS is not set
CONFIG_RT_USING_INTERRUPT_INFO=y
CONFIG_RT_USING_CONSOLE=y
CONFIG_RT_CONSOLEBUF_SIZE=4096
CONFIG_RT_CONSOLE_DEVICE_NAME="uart1"
CONFIG_RT_VER_NUM=0x40004
CONFIG_ARCH_ARM=y
# CONFIG_RT_USING_CPU_FFS is not set
CONFIG_ARCH_ARM_CORTEX_A=y
# CONFIG_RT_SMP_AUTO_BOOT is not set
# CONFIG_RT_USING_GIC_V2 is not set
CONFIG_RT_USING_GIC_V3=y
# CONFIG_RT_NO_USING_GIC is not set
# CONFIG_ARCH_CPU_STACK_GROWS_UPWARD is not set
#
# RT-Thread Components
#
CONFIG_RT_USING_COMPONENTS_INIT=y
CONFIG_RT_USING_USER_MAIN=y
CONFIG_RT_MAIN_THREAD_STACK_SIZE=2048
CONFIG_RT_MAIN_THREAD_PRIORITY=10
#
# C++ features
#
# CONFIG_RT_USING_CPLUSPLUS is not set
#
# Command shell
#
CONFIG_RT_USING_FINSH=y
CONFIG_FINSH_THREAD_NAME="tshell"
CONFIG_FINSH_USING_HISTORY=y
CONFIG_FINSH_HISTORY_LINES=5
CONFIG_FINSH_USING_SYMTAB=y
CONFIG_FINSH_USING_DESCRIPTION=y
# CONFIG_FINSH_ECHO_DISABLE_DEFAULT is not set
CONFIG_FINSH_THREAD_PRIORITY=20
CONFIG_FINSH_THREAD_STACK_SIZE=4096
CONFIG_FINSH_CMD_SIZE=128
# CONFIG_FINSH_USING_AUTH is not set
CONFIG_FINSH_USING_MSH=y
CONFIG_FINSH_USING_MSH_DEFAULT=y
# CONFIG_FINSH_USING_MSH_ONLY is not set
CONFIG_FINSH_ARG_MAX=10
#
# Device virtual file system
#
CONFIG_RT_USING_DFS=y
CONFIG_DFS_USING_WORKDIR=y
CONFIG_DFS_FILESYSTEMS_MAX=2
CONFIG_DFS_FILESYSTEM_TYPES_MAX=2
CONFIG_DFS_FD_MAX=16
# CONFIG_RT_USING_DFS_MNTTABLE is not set
CONFIG_RT_USING_DFS_ELMFAT=y
#
# elm-chan's FatFs, Generic FAT Filesystem Module
#
CONFIG_RT_DFS_ELM_CODE_PAGE=437
CONFIG_RT_DFS_ELM_WORD_ACCESS=y
# CONFIG_RT_DFS_ELM_USE_LFN_0 is not set
# CONFIG_RT_DFS_ELM_USE_LFN_1 is not set
# CONFIG_RT_DFS_ELM_USE_LFN_2 is not set
CONFIG_RT_DFS_ELM_USE_LFN_3=y
CONFIG_RT_DFS_ELM_USE_LFN=3
CONFIG_RT_DFS_ELM_LFN_UNICODE_0=y
# CONFIG_RT_DFS_ELM_LFN_UNICODE_1 is not set
# CONFIG_RT_DFS_ELM_LFN_UNICODE_2 is not set
# CONFIG_RT_DFS_ELM_LFN_UNICODE_3 is not set
CONFIG_RT_DFS_ELM_LFN_UNICODE=0
CONFIG_RT_DFS_ELM_MAX_LFN=255
CONFIG_RT_DFS_ELM_DRIVES=2
CONFIG_RT_DFS_ELM_MAX_SECTOR_SIZE=512
# CONFIG_RT_DFS_ELM_USE_ERASE is not set
CONFIG_RT_DFS_ELM_REENTRANT=y
CONFIG_RT_USING_DFS_DEVFS=y
# CONFIG_RT_USING_DFS_ROMFS is not set
# CONFIG_RT_USING_DFS_RAMFS is not set
# CONFIG_RT_USING_DFS_NFS is not set
#
# Device Drivers
#
CONFIG_RT_USING_DEVICE_IPC=y
CONFIG_RT_PIPE_BUFSZ=512
# CONFIG_RT_USING_SYSTEM_WORKQUEUE is not set
CONFIG_RT_USING_SERIAL=y
CONFIG_RT_SERIAL_USING_DMA=y
CONFIG_RT_SERIAL_RB_BUFSZ=256
CONFIG_RT_USING_CAN=y
# CONFIG_RT_CAN_USING_HDR is not set
# CONFIG_RT_USING_HWTIMER is not set
# CONFIG_RT_USING_CPUTIME is not set
# CONFIG_RT_USING_I2C is not set
# CONFIG_RT_USING_PHY is not set
# CONFIG_RT_USING_PIN is not set
# CONFIG_RT_USING_ADC is not set
# CONFIG_RT_USING_DAC is not set
# CONFIG_RT_USING_PWM is not set
# CONFIG_RT_USING_MTD_NOR is not set
# CONFIG_RT_USING_MTD_NAND is not set
# CONFIG_RT_USING_PM is not set
# CONFIG_RT_USING_RTC is not set
CONFIG_RT_USING_SDIO=y
CONFIG_RT_SDIO_STACK_SIZE=512
CONFIG_RT_SDIO_THREAD_PRIORITY=15
CONFIG_RT_MMCSD_STACK_SIZE=1024
CONFIG_RT_MMCSD_THREAD_PREORITY=22
CONFIG_RT_MMCSD_MAX_PARTITION=16
# CONFIG_RT_SDIO_DEBUG is not set
CONFIG_RT_USING_SPI=y
CONFIG_RT_USING_QSPI=y
# CONFIG_RT_USING_SPI_MSD is not set
CONFIG_RT_USING_SFUD=y
CONFIG_RT_SFUD_USING_SFDP=y
CONFIG_RT_SFUD_USING_FLASH_INFO_TABLE=y
CONFIG_RT_SFUD_USING_QSPI=y
CONFIG_RT_SFUD_SPI_MAX_HZ=50000000
# CONFIG_RT_DEBUG_SFUD is not set
# CONFIG_RT_USING_ENC28J60 is not set
# CONFIG_RT_USING_SPI_WIFI is not set
# CONFIG_RT_USING_WDT is not set
# CONFIG_RT_USING_AUDIO is not set
# CONFIG_RT_USING_SENSOR is not set
# CONFIG_RT_USING_TOUCH is not set
# CONFIG_RT_USING_HWCRYPTO is not set
# CONFIG_RT_USING_PULSE_ENCODER is not set
# CONFIG_RT_USING_INPUT_CAPTURE is not set
# CONFIG_RT_USING_WIFI is not set
#
# Using USB
#
# CONFIG_RT_USING_USB_HOST is not set
# CONFIG_RT_USING_USB_DEVICE is not set
#
# POSIX layer and C standard library
#
CONFIG_RT_USING_LIBC=y
# CONFIG_RT_USING_PTHREADS is not set
CONFIG_RT_USING_POSIX=y
# CONFIG_RT_USING_POSIX_MMAP is not set
# CONFIG_RT_USING_POSIX_TERMIOS is not set
# CONFIG_RT_USING_POSIX_GETLINE is not set
# CONFIG_RT_USING_POSIX_AIO is not set
# CONFIG_RT_USING_MODULE is not set
CONFIG_RT_LIBC_FIXED_TIMEZONE=8
#
# Network
#
#
# Socket abstraction layer
#
# CONFIG_RT_USING_SAL is not set
#
# Network interface device
#
CONFIG_RT_USING_NETDEV=y
CONFIG_NETDEV_USING_IFCONFIG=y
CONFIG_NETDEV_USING_PING=y
CONFIG_NETDEV_USING_NETSTAT=y
CONFIG_NETDEV_USING_AUTO_DEFAULT=y
# CONFIG_NETDEV_USING_IPV6 is not set
CONFIG_NETDEV_IPV4=1
CONFIG_NETDEV_IPV6=0
# CONFIG_NETDEV_IPV6_SCOPES is not set
#
# light weight TCP/IP stack
#
CONFIG_RT_USING_LWIP=y
# CONFIG_RT_USING_LWIP141 is not set
# CONFIG_RT_USING_LWIP202 is not set
CONFIG_RT_USING_LWIP212=y
# CONFIG_RT_USING_LWIP_IPV6 is not set
CONFIG_RT_LWIP_MEM_ALIGNMENT=4
CONFIG_RT_LWIP_IGMP=y
CONFIG_RT_LWIP_ICMP=y
# CONFIG_RT_LWIP_SNMP is not set
CONFIG_RT_LWIP_DNS=y
# CONFIG_RT_LWIP_DHCP is not set
#
# Static IPv4 Address
#
CONFIG_RT_LWIP_IPADDR="192.168.3.20"
CONFIG_RT_LWIP_GWADDR="192.168.3.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_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_TCP_SEG_NUM=40
CONFIG_RT_LWIP_TCP_SND_BUF=8196
CONFIG_RT_LWIP_TCP_WND=8196
CONFIG_RT_LWIP_TCPTHREAD_PRIORITY=10
CONFIG_RT_LWIP_TCPTHREAD_MBOX_SIZE=8
CONFIG_RT_LWIP_TCPTHREAD_STACKSIZE=1024
# 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=1024
CONFIG_RT_LWIP_ETHTHREAD_MBOX_SIZE=8
# CONFIG_RT_LWIP_REASSEMBLY_FRAG is not set
CONFIG_LWIP_NETIF_STATUS_CALLBACK=1
CONFIG_LWIP_NETIF_LINK_CALLBACK=1
CONFIG_SO_REUSE=1
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_STATS is not set
# CONFIG_RT_LWIP_USING_HW_CHECKSUM is not set
CONFIG_RT_LWIP_USING_PING=y
# CONFIG_RT_LWIP_DEBUG is not set
#
# AT commands
#
# CONFIG_RT_USING_AT is not set
# CONFIG_LWIP_USING_DHCPD is not set
#
# VBUS(Virtual Software BUS)
#
# CONFIG_RT_USING_VBUS is not set
#
# Utilities
#
# CONFIG_RT_USING_RYM is not set
CONFIG_RT_USING_ULOG=y
# CONFIG_ULOG_OUTPUT_LVL_A is not set
# CONFIG_ULOG_OUTPUT_LVL_E is not set
CONFIG_ULOG_OUTPUT_LVL_W=y
# CONFIG_ULOG_OUTPUT_LVL_I is not set
# CONFIG_ULOG_OUTPUT_LVL_D is not set
CONFIG_ULOG_OUTPUT_LVL=4
# CONFIG_ULOG_USING_ISR_LOG is not set
CONFIG_ULOG_ASSERT_ENABLE=y
CONFIG_ULOG_LINE_BUF_SIZE=128
# CONFIG_ULOG_USING_ASYNC_OUTPUT is not set
#
# log format
#
# CONFIG_ULOG_OUTPUT_FLOAT is not set
CONFIG_ULOG_USING_COLOR=y
CONFIG_ULOG_OUTPUT_TIME=y
# CONFIG_ULOG_TIME_USING_TIMESTAMP is not set
CONFIG_ULOG_OUTPUT_LEVEL=y
CONFIG_ULOG_OUTPUT_TAG=y
# CONFIG_ULOG_OUTPUT_THREAD_NAME is not set
CONFIG_ULOG_BACKEND_USING_CONSOLE=y
# CONFIG_ULOG_USING_FILTER is not set
# CONFIG_ULOG_USING_SYSLOG is not set
# CONFIG_RT_USING_UTEST is not set
# CONFIG_RT_USING_RT_LINK is not set
# CONFIG_RT_USING_LWP is not set
#
# RT-Thread Utestcases
#
# CONFIG_RT_USING_UTESTCASES is not set
#
# RT-Thread online packages
#
#
# IoT - internet of things
#
# CONFIG_PKG_USING_LORAWAN_DRIVER is not set
# CONFIG_PKG_USING_PAHOMQTT is not set
# CONFIG_PKG_USING_UMQTT is not set
# CONFIG_PKG_USING_WEBCLIENT is not set
# CONFIG_PKG_USING_WEBNET is not set
# CONFIG_PKG_USING_MONGOOSE is not set
# CONFIG_PKG_USING_MYMQTT is not set
# CONFIG_PKG_USING_KAWAII_MQTT is not set
# CONFIG_PKG_USING_BC28_MQTT is not set
# CONFIG_PKG_USING_WEBTERMINAL is not set
# CONFIG_PKG_USING_CJSON is not set
# CONFIG_PKG_USING_JSMN is not set
# CONFIG_PKG_USING_LIBMODBUS is not set
# CONFIG_PKG_USING_FREEMODBUS is not set
# CONFIG_PKG_USING_LJSON is not set
# CONFIG_PKG_USING_EZXML is not set
# CONFIG_PKG_USING_NANOPB is not set
#
# Wi-Fi
#
#
# Marvell WiFi
#
# CONFIG_PKG_USING_WLANMARVELL is not set
#
# Wiced WiFi
#
# CONFIG_PKG_USING_WLAN_WICED is not set
# CONFIG_PKG_USING_RW007 is not set
# CONFIG_PKG_USING_COAP is not set
# CONFIG_PKG_USING_NOPOLL is not set
# CONFIG_PKG_USING_NETUTILS is not set
# CONFIG_PKG_USING_CMUX is not set
# CONFIG_PKG_USING_PPP_DEVICE is not set
# CONFIG_PKG_USING_AT_DEVICE is not set
# CONFIG_PKG_USING_ATSRV_SOCKET is not set
# CONFIG_PKG_USING_WIZNET is not set
#
# IoT Cloud
#
# CONFIG_PKG_USING_ONENET is not set
# CONFIG_PKG_USING_GAGENT_CLOUD is not set
# CONFIG_PKG_USING_ALI_IOTKIT is not set
# CONFIG_PKG_USING_AZURE is not set
# CONFIG_PKG_USING_TENCENT_IOT_EXPLORER is not set
# CONFIG_PKG_USING_JIOT-C-SDK is not set
# CONFIG_PKG_USING_UCLOUD_IOT_SDK is not set
# CONFIG_PKG_USING_JOYLINK is not set
# CONFIG_PKG_USING_NIMBLE is not set
# CONFIG_PKG_USING_OTA_DOWNLOADER is not set
# CONFIG_PKG_USING_IPMSG is not set
# CONFIG_PKG_USING_LSSDP is not set
# CONFIG_PKG_USING_AIRKISS_OPEN is not set
# CONFIG_PKG_USING_LIBRWS is not set
# CONFIG_PKG_USING_TCPSERVER is not set
# CONFIG_PKG_USING_PROTOBUF_C is not set
# CONFIG_PKG_USING_DLT645 is not set
# CONFIG_PKG_USING_QXWZ is not set
# CONFIG_PKG_USING_SMTP_CLIENT is not set
# CONFIG_PKG_USING_ABUP_FOTA is not set
# CONFIG_PKG_USING_LIBCURL2RTT is not set
# CONFIG_PKG_USING_CAPNP is not set
# CONFIG_PKG_USING_RT_CJSON_TOOLS is not set
# CONFIG_PKG_USING_AGILE_TELNET is not set
# CONFIG_PKG_USING_NMEALIB is not set
# CONFIG_PKG_USING_AGILE_JSMN is not set
# CONFIG_PKG_USING_PDULIB is not set
# CONFIG_PKG_USING_BTSTACK is not set
# CONFIG_PKG_USING_LORAWAN_ED_STACK is not set
# CONFIG_PKG_USING_WAYZ_IOTKIT is not set
# CONFIG_PKG_USING_MAVLINK is not set
# CONFIG_PKG_USING_RAPIDJSON is not set
# CONFIG_PKG_USING_BSAL is not set
# CONFIG_PKG_USING_AGILE_MODBUS is not set
# CONFIG_PKG_USING_AGILE_FTP is not set
# CONFIG_PKG_USING_EMBEDDEDPROTO is not set
#
# security packages
#
# CONFIG_PKG_USING_MBEDTLS is not set
# CONFIG_PKG_USING_libsodium is not set
# CONFIG_PKG_USING_TINYCRYPT is not set
# CONFIG_PKG_USING_TFM is not set
# CONFIG_PKG_USING_YD_CRYPTO is not set
#
# language packages
#
# CONFIG_PKG_USING_LUA is not set
# CONFIG_PKG_USING_JERRYSCRIPT is not set
# CONFIG_PKG_USING_MICROPYTHON is not set
#
# multimedia packages
#
# CONFIG_PKG_USING_OPENMV is not set
# CONFIG_PKG_USING_MUPDF is not set
# CONFIG_PKG_USING_STEMWIN is not set
# CONFIG_PKG_USING_WAVPLAYER is not set
# CONFIG_PKG_USING_TJPGD is not set
# CONFIG_PKG_USING_PDFGEN is not set
# CONFIG_PKG_USING_HELIX is not set
# CONFIG_PKG_USING_AZUREGUIX is not set
# CONFIG_PKG_USING_TOUCHGFX2RTT is not set
# CONFIG_PKG_USING_NUEMWIN is not set
#
# tools packages
#
# CONFIG_PKG_USING_CMBACKTRACE is not set
# CONFIG_PKG_USING_EASYFLASH is not set
# CONFIG_PKG_USING_EASYLOGGER is not set
# CONFIG_PKG_USING_SYSTEMVIEW is not set
# CONFIG_PKG_USING_SEGGER_RTT is not set
# CONFIG_PKG_USING_RDB is not set
# CONFIG_PKG_USING_QRCODE is not set
# CONFIG_PKG_USING_ULOG_EASYFLASH is not set
# CONFIG_PKG_USING_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
# CONFIG_PKG_USING_DHRYSTONE is not set
# CONFIG_PKG_USING_MEMORYPERF is not set
# CONFIG_PKG_USING_NR_MICRO_SHELL is not set
# CONFIG_PKG_USING_CHINESE_FONT_LIBRARY is not set
# CONFIG_PKG_USING_LUNAR_CALENDAR is not set
# CONFIG_PKG_USING_BS8116A is not set
# CONFIG_PKG_USING_GPS_RMC is not set
# CONFIG_PKG_USING_URLENCODE is not set
# CONFIG_PKG_USING_UMCN is not set
# CONFIG_PKG_USING_LWRB2RTT is not set
# CONFIG_PKG_USING_CPU_USAGE is not set
# CONFIG_PKG_USING_GBK2UTF8 is not set
# CONFIG_PKG_USING_VCONSOLE is not set
# CONFIG_PKG_USING_KDB is not set
# CONFIG_PKG_USING_WAMR is not set
# CONFIG_PKG_USING_MICRO_XRCE_DDS_CLIENT is not set
# CONFIG_PKG_USING_LWLOG is not set
# CONFIG_PKG_USING_ANV_TRACE is not set
# CONFIG_PKG_USING_ANV_MEMLEAK is not set
# CONFIG_PKG_USING_ANV_TESTSUIT is not set
# CONFIG_PKG_USING_ANV_BENCH is not set
# CONFIG_PKG_USING_DEVMEM is not set
# CONFIG_PKG_USING_REGEX is not set
# CONFIG_PKG_USING_MEM_SANDBOX is not set
# CONFIG_PKG_USING_SOLAR_TERMS is not set
# CONFIG_PKG_USING_GAN_ZHI is not set
#
# system packages
#
#
# acceleration: Assembly language or algorithmic acceleration packages
#
# CONFIG_PKG_USING_RT_MEMCPY_CM is not set
# CONFIG_PKG_USING_QFPLIB_M0_FULL is not set
# CONFIG_PKG_USING_QFPLIB_M0_TINY is not set
# CONFIG_PKG_USING_QFPLIB_M3 is not set
#
# Micrium: Micrium software products porting for RT-Thread
#
# CONFIG_PKG_USING_UCOSIII_WRAPPER is not set
# CONFIG_PKG_USING_UCOSII_WRAPPER is not set
# CONFIG_PKG_USING_UC_CRC is not set
# CONFIG_PKG_USING_UC_CLK is not set
# CONFIG_PKG_USING_UC_COMMON is not set
# CONFIG_PKG_USING_UC_MODBUS is not set
# CONFIG_PKG_USING_GUIENGINE is not set
# CONFIG_PKG_USING_PERSIMMON is not set
# CONFIG_PKG_USING_CAIRO is not set
# CONFIG_PKG_USING_PIXMAN is not set
# CONFIG_PKG_USING_PARTITION is not set
# CONFIG_PKG_USING_FAL is not set
# CONFIG_PKG_USING_FLASHDB is not set
# CONFIG_PKG_USING_SQLITE is not set
# CONFIG_PKG_USING_RTI is not set
# CONFIG_PKG_USING_LITTLEVGL2RTT is not set
# CONFIG_PKG_USING_CMSIS is not set
# CONFIG_PKG_USING_DFS_YAFFS is not set
# CONFIG_PKG_USING_LITTLEFS is not set
# CONFIG_PKG_USING_DFS_JFFS2 is not set
# CONFIG_PKG_USING_DFS_UFFS is not set
# CONFIG_PKG_USING_LWEXT4 is not set
# CONFIG_PKG_USING_THREAD_POOL is not set
# CONFIG_PKG_USING_ROBOTS is not set
# CONFIG_PKG_USING_EV is not set
# CONFIG_PKG_USING_SYSWATCH is not set
# CONFIG_PKG_USING_SYS_LOAD_MONITOR is not set
# CONFIG_PKG_USING_PLCCORE is not set
# CONFIG_PKG_USING_RAMDISK is not set
# CONFIG_PKG_USING_MININI is not set
# CONFIG_PKG_USING_QBOOT is not set
# CONFIG_PKG_USING_PPOOL is not set
# CONFIG_PKG_USING_OPENAMP is not set
# CONFIG_PKG_USING_RT_KPRINTF_THREADSAFE is not set
# CONFIG_PKG_USING_LPM is not set
# CONFIG_PKG_USING_TLSF is not set
# CONFIG_PKG_USING_EVENT_RECORDER is not set
#
# peripheral libraries and drivers
#
# CONFIG_PKG_USING_SENSORS_DRIVERS is not set
# CONFIG_PKG_USING_REALTEK_AMEBA is not set
# CONFIG_PKG_USING_SHT2X is not set
# CONFIG_PKG_USING_SHT3X is not set
# CONFIG_PKG_USING_AS7341 is not set
# CONFIG_PKG_USING_STM32_SDIO is not set
# CONFIG_PKG_USING_ICM20608 is not set
# CONFIG_PKG_USING_U8G2 is not set
# CONFIG_PKG_USING_BUTTON is not set
# CONFIG_PKG_USING_PCF8574 is not set
# CONFIG_PKG_USING_SX12XX is not set
# CONFIG_PKG_USING_SIGNAL_LED is not set
# CONFIG_PKG_USING_LEDBLINK is not set
# CONFIG_PKG_USING_LITTLED is not set
# CONFIG_PKG_USING_LKDGUI is not set
# CONFIG_PKG_USING_NRF5X_SDK is not set
# CONFIG_PKG_USING_NRFX is not set
# CONFIG_PKG_USING_WM_LIBRARIES is not set
# CONFIG_PKG_USING_KENDRYTE_SDK is not set
# CONFIG_PKG_USING_INFRARED is not set
# CONFIG_PKG_USING_ROSSERIAL is not set
# CONFIG_PKG_USING_AGILE_BUTTON is not set
# CONFIG_PKG_USING_AGILE_LED is not set
# CONFIG_PKG_USING_AT24CXX is not set
# CONFIG_PKG_USING_MOTIONDRIVER2RTT is not set
# CONFIG_PKG_USING_AD7746 is not set
# CONFIG_PKG_USING_PCA9685 is not set
# CONFIG_PKG_USING_I2C_TOOLS is not set
# CONFIG_PKG_USING_NRF24L01 is not set
# CONFIG_PKG_USING_TOUCH_DRIVERS is not set
# CONFIG_PKG_USING_MAX17048 is not set
# CONFIG_PKG_USING_RPLIDAR is not set
# CONFIG_PKG_USING_AS608 is not set
# CONFIG_PKG_USING_RC522 is not set
# CONFIG_PKG_USING_WS2812B is not set
# CONFIG_PKG_USING_EMBARC_BSP is not set
# CONFIG_PKG_USING_EXTERN_RTC_DRIVERS is not set
# CONFIG_PKG_USING_MULTI_RTIMER is not set
# CONFIG_PKG_USING_MAX7219 is not set
# CONFIG_PKG_USING_BEEP is not set
# CONFIG_PKG_USING_EASYBLINK is not set
# CONFIG_PKG_USING_PMS_SERIES is not set
# CONFIG_PKG_USING_CAN_YMODEM is not set
# CONFIG_PKG_USING_LORA_RADIO_DRIVER is not set
# CONFIG_PKG_USING_QLED is not set
# CONFIG_PKG_USING_PAJ7620 is not set
# CONFIG_PKG_USING_AGILE_CONSOLE is not set
# CONFIG_PKG_USING_LD3320 is not set
# CONFIG_PKG_USING_WK2124 is not set
# CONFIG_PKG_USING_LY68L6400 is not set
# CONFIG_PKG_USING_DM9051 is not set
# CONFIG_PKG_USING_SSD1306 is not set
# CONFIG_PKG_USING_QKEY is not set
# CONFIG_PKG_USING_RS485 is not set
# CONFIG_PKG_USING_NES is not set
# CONFIG_PKG_USING_VIRTUAL_SENSOR is not set
# CONFIG_PKG_USING_VDEVICE is not set
# CONFIG_PKG_USING_SGM706 is not set
# CONFIG_PKG_USING_STM32WB55_SDK is not set
# CONFIG_PKG_USING_RDA58XX is not set
# CONFIG_PKG_USING_LIBNFC is not set
# CONFIG_PKG_USING_MFOC is not set
# CONFIG_PKG_USING_TMC51XX is not set
# CONFIG_PKG_USING_TCA9534 is not set
#
# AI packages
#
# CONFIG_PKG_USING_LIBANN is not set
# CONFIG_PKG_USING_NNOM is not set
# CONFIG_PKG_USING_ONNX_BACKEND is not set
# CONFIG_PKG_USING_ONNX_PARSER is not set
# CONFIG_PKG_USING_TENSORFLOWLITEMICRO is not set
# CONFIG_PKG_USING_ELAPACK is not set
# CONFIG_PKG_USING_ULAPACK is not set
# CONFIG_PKG_USING_QUEST is not set
# CONFIG_PKG_USING_NAXOS is not set
#
# miscellaneous packages
#
# CONFIG_PKG_USING_LIBCSV is not set
# CONFIG_PKG_USING_OPTPARSE is not set
# CONFIG_PKG_USING_FASTLZ is not set
# CONFIG_PKG_USING_MINILZO is not set
# CONFIG_PKG_USING_QUICKLZ is not set
# CONFIG_PKG_USING_LZMA is not set
# CONFIG_PKG_USING_MULTIBUTTON is not set
# CONFIG_PKG_USING_FLEXIBLE_BUTTON is not set
# CONFIG_PKG_USING_CANFESTIVAL is not set
# CONFIG_PKG_USING_ZLIB is not set
# CONFIG_PKG_USING_MINIZIP is not set
# CONFIG_PKG_USING_DSTR is not set
# CONFIG_PKG_USING_TINYFRAME is not set
# CONFIG_PKG_USING_KENDRYTE_DEMO is not set
# CONFIG_PKG_USING_DIGITALCTRL is not set
# CONFIG_PKG_USING_UPACKER is not set
# CONFIG_PKG_USING_UPARAM is not set
#
# samples: kernel and components samples
#
# CONFIG_PKG_USING_KERNEL_SAMPLES is not set
# CONFIG_PKG_USING_FILESYSTEM_SAMPLES is not set
# CONFIG_PKG_USING_NETWORK_SAMPLES is not set
# CONFIG_PKG_USING_PERIPHERAL_SAMPLES is not set
# CONFIG_PKG_USING_HELLO is not set
# CONFIG_PKG_USING_VI is not set
# CONFIG_PKG_USING_KI is not set
# CONFIG_PKG_USING_ARMv7M_DWT is not set
# CONFIG_PKG_USING_VT100 is not set
# CONFIG_PKG_USING_UKAL is not set
# CONFIG_PKG_USING_CRCLIB is not set
#
# entertainment: terminal games and other interesting software packages
#
# CONFIG_PKG_USING_THREES is not set
# CONFIG_PKG_USING_2048 is not set
# CONFIG_PKG_USING_SNAKE is not set
# CONFIG_PKG_USING_TETRIS is not set
# CONFIG_PKG_USING_DONUT is not set
# CONFIG_PKG_USING_ACLOCK is not set
# CONFIG_PKG_USING_LWGPS is not set
# CONFIG_PKG_USING_STATE_MACHINE is not set
# CONFIG_PKG_USING_MCURSES is not set
# CONFIG_PKG_USING_COWSAY is not set
CONFIG_FT2004=y
#
# Hardware Drivers Config
#
#
# On-chip Peripheral Drivers
#
CONFIG_BSP_USING_UART=y
CONFIG_RT_USING_UART1=y
# CONFIG_RT_USING_UART0 is not set
CONFIG_BSP_USING_SDC=y
# CONFIG_BSP_SDC_DEBUG_PRINT is not set
# CONFIG_BSP_SDC_USE_IRQ is not set
CONFIG_BSP_USING_GMAC=y
# CONFIG_BSP_USING_GMAC0 is not set
CONFIG_BSP_USING_GMAC1=y
CONFIG_RT_LWIP_ETH_PAD_SIZE=2
# CONFIG_RAW_DATA_PRINT is not set
CONFIG_BSP_USE_SPI=y
# CONFIG_BSP_SPI_DEBUG is not set
CONFIG_BSP_USE_GPIO=y
# CONFIG_BSP_GPIO_DEBUG is not set
CONFIG_BSP_USE_CAN=y
CONFIG_BSP_USING_CAN0=y
# CONFIG_BSP_USING_CAN1 is not set
# CONFIG_BSP_USING_CAN0_DEBUG is not set
#
# Board extended module Drivers
#

30
bsp/ft2004/Kconfig Normal file
View File

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

236
bsp/ft2004/README.md Normal file
View File

@ -0,0 +1,236 @@
# ft2004 四核开发板 BSP 说明
## 简介
本文档为 飞腾技术公司 ft2000/4 开发板的 BSP (板级支持包) 说明。
主要内容如下:
- 开发板资源介绍
- BSP 外设支持
- 使用方法
- 相关实验
### 1. 开发板资源介绍
FT-2000/4 是一款面向桌面应用的高性能通用 4 核处理器。每 2 个核构成 1
个处理器核簇Cluster并共享 L2 Cache。主要技术特征如下
- 兼容 ARM v8 64 位指令系统,兼容 32 位指令
- 支持单精度、双精度浮点运算指令
- 支持 ASIMD 处理指令
- 集成 2 个 DDR4 通道,可对 DDR 存储数据进行实时加密
- 集成 34 Lane PCIE3.0 接口2 个 X16每个可拆分成 2 个 X82 个 X1
- 集成 2 个 GMACRGMII 接口,支持 10/100/1000 自适应
- 集成 1 个 SD 卡控制器,兼容 SD 2.0 规范
- 集成 1 个 HDAudio支持音频输出可同时支持最多 4 个 Codec
- 集成 SM2、SM3、SM4 模块
- 集成 4 个 UART1 个 LPC32 个 GPIO4 个 I2C1 个 QSPI2 个通
用 SPI2 个 WDT16 个外部中断(和 GPIO 共用 IO
- 集成温度传感器
### 2. BSP 外设支持
| 外设名 | 支持情况 | 备注 |
| -------- | -------- | ---------------------- |
| ft_gicv3 | 支持 | gicv3 中断控制器 |
| ft_gmac | 支持 | ft gmac 千兆网卡控制器 |
| ft_i2c | 支持 | FT I2C |
| ft_qspi | 支持 | FT qspi 控制器 |
| ft_sd | 支持 | FT mmcsd 控制器 |
| ft_uart | 支持 | PrimeCell PL011 |
| ft_spi | 支持 | FT spi 控制器 |
| ft_gpio | 支持 | FT gpio 控制器 |
| ft_can | 支持 | FT can 控制器 |
### 3. 使用方法
#### ubuntu 上环境搭建
1. 在 ubuntu 环境下通过指令,下载并安装交叉编译链
```
sudo apt-get install gcc-arm-none-eabi
```
2. 安装之后,通过指令,确定交叉编译链安装完毕
```
arm-none-eabi-gcc -v
```
3. 搭建 tftp 环境
- 在主机安装 tftp 服务
> 使用 ubuntu 完成下列操作
```
sudo apt-get install tftp-hpa tftpd-hpa
sudo apt-get install xinetd
```
- 新建 tftboot 目录,如:
`/mnt/d/tftboot`
> 需要给 tftboot 目录执行权限`chmod 777 /**/tftboot`
- 配置主机 tftpboot 服务
新建并配置文件/etc/xinetd.d/tftp
```
# /etc/xinetd.d/tftp
server tftp
{
socket_type = dgram
protocol = udp
wait = yes
user = root
server = /usr/sbin/in.tftpd
server_args = -s /mnt/d/tftboot
disable = no
per_source = 11
cps = 100 2
flags = IPv4
}
```
- 启动主机 tftp 服务
```
sudo service tftpd-hpa start
```
- 修改主机 tftp 配置
修改/etc/default/tftpd-hpa
```
sudo nano /etc/default/tftpd-hpa
# /etc/default/tftpd-hpa
TFTP_USERNAME="tftp"
TFTP_DIRECTORY="/mnt/d/tftboot"
TFTP_ADDRESS=":69"
TFTP_OPTIONS="-l -c -s"
```
- 重启主机 tftp 服务
> 每次开机要重启一次
```
sudo service tftpd-hpa restart
```
- 测试主机 tftp 服务的可用性
> 登录 tftp 服务,获取一个文件
```
$ tftp 192.168.4.50
tftp> get test1234
tftp> q
```
#### 执行
1. 将本 bsp 包拷贝至 RT-THREAD bsp/目录下
1. 在 Ubuntu 终端下,切换至 bsp 目录
```
cd rt-thread/bsp/ft2004
```
3. 使用 scons -c 清空工程缓存
4. 使用 scons --menuconfig 配置需要的外设
![](./figures/onchipPeripheral.png)
5. 使用 scons 编译代码,得到 rtthread.bin并将 rtthread.bin 放入之前配置的 tftp 路径下。
6. 连接开发板对应串口到 PC, 在终端工具里打开相应的串口115200-8-1-N
7. 将开发板网线接入局域网中
8. 本开发板自带 uboot使用 uboot 自带 指令进行将 bin 文件下载至 ram 中
```
setenv ipaddr 192.168.x.x # 设置开发板ip
setenv serverip 192.168.x.x # 设置tftp服务器ip
setenv gatewayip 192.168.x.x # 设置网关ip
tftpboot 80100000 rtthread.bin # 在主机 /tftpboot目录中的rtthread.bin文件下载到开发板内存的80100000地址中。
```
7. 执行跳转指令,便可以正常执行
```
bootvx32 80100000
boot32 80100000
```
![](./figures/启动演示图.png)
### 5. 相关实验
#### 网卡
- 主机 ping 本机 指令 sudo ping 192.168.3.20 (默认)
- rtt ping 主机 指令 ping 192.168.x.x (根据实际情况)
- 通过界面
![](./figures/rttPing通过界面.png)
#### sd 卡调试
- 通过基本命令进行mv echo ls cd rm ....
![](./figures/rttsd调试.png)
#### spi flash 卡调试
- 找一块有 spi flash 插槽的 ft-2004 开发板,插入 sf25s 或 gd25q 系列 spi flash
- 配置 rt-thread 的编译选项,打开 BSP_USE_SPI 和 BSP_USE_GPIO 配置,关闭 BSP_USE_QSPI 配置,打开 rt-thread 的 SFUD 调试开关
- 编译 rt-thread加载版本启动启动后显示 spi flash probe 成功
- 执行 sf 基本操作read, write, erase
#### 推荐指令
1. sf probe S25FS256
2. sf read 0x1FFF000 16
3. sf write 0x1FFF000 16 25 68 78 95 15 75 20
4. sf read 0x1FFF000 16
5. sf erase 0x1FFF000 16
#### can 测试
1. 使用 scons menuconfig 选中 Enable Can
2. 然后选中 Enable can0 Enable can0 work in loop back
3. 烧录程序并且烧录
4. 打开 can 盒,将波特率设为 1000000
5. 然后通过 can 盒发送对应的数据(标准帧,扩展帧),就可以看见回复同样的内容
## 6. 参考资源
- ARM Architecture Reference Manual
- FT-20004 软件编程手册-V1.4
## 7. 联系人信息
请联系飞腾嵌入式软件部
huanghe@phytium.com.cn
zhugengyu@phytium.com.cn

14
bsp/ft2004/SConscript Normal file
View File

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

32
bsp/ft2004/SConstruct Normal file
View File

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

View File

@ -0,0 +1,11 @@
Import('RTT_ROOT')
Import('rtconfig')
from building import *
cwd = GetCurrentDir()
src = Glob('*.c')
CPPPATH = [cwd]
group = DefineGroup('Applications', src, depend = [''], CPPPATH = CPPPATH)
Return('group')

View File

@ -0,0 +1,77 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2012-12-05 Bernard the first version
*/
#include <rthw.h>
#include <rtthread.h>
#include "ft_cpu.h"
#include "ft_generic_timer.h"
#include <board.h>
#ifdef RT_USING_SMP
struct rt_thread test_core[RT_CPUS_NR];
static char *core_thread_name[RT_CPUS_NR] = {
"core0_test",
"core1_test",
"core2_test",
"core3_test"};
static rt_uint8_t core_stack[RT_CPUS_NR][1024];
static void demo_core_thread(void *parameter)
{
rt_base_t level;
while (1)
{
/* code */
level = rt_cpus_lock();
rt_kprintf("Hi, core%d \r\n", FCpu_IdGet());
rt_cpus_unlock(level);
rt_thread_mdelay(20000);
}
}
void demo_core(void)
{
rt_ubase_t i;
rt_uint8_t cpu_id = 0;
for (i = 0; i < RT_CPUS_NR; i++)
{
cpu_id = i;
rt_thread_init(&test_core[i],
core_thread_name[i],
demo_core_thread,
RT_NULL,
&core_stack[i],
1024,
20,
32);
rt_thread_control(&test_core[i], RT_THREAD_CTRL_BIND_CPU, (void *)cpu_id);
rt_thread_startup(&test_core[i]);
}
}
#endif
int main(void)
{
int count = 1;
#ifdef RT_USING_SMP
demo_core();
#endif
while (count++)
{
rt_thread_mdelay(2000);
}
return RT_EOK;
}

View File

@ -0,0 +1,14 @@
from building import *
cwd = GetCurrentDir()
src = Glob('*.S')
src += Glob('*.c')
CPPPATH = [cwd]
group = DefineGroup('Drivers', src, depend = [''], CPPPATH = CPPPATH)
Return('group')

155
bsp/ft2004/drivers/board.c Normal file
View File

@ -0,0 +1,155 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2021-03-04 Carl the first version
*
*/
#include <rtthread.h>
#include "ft_printf.h"
#include "ft_assert.h"
#include "ft_cpu.h"
#include "ft_psci.h"
#include "ft_parameters.h"
#include "board.h"
#include "gtimer.h"
#include "ft_generic_timer.h"
#include <gicv3.h>
#include "interrupt.h"
#include <mmu.h>
#include "cp15.h"
#include "ft2004.h"
#define DDR_MEM (SHARED | AP_RW | DOMAIN0 | MEMWT | DESC_SEC)
struct mem_desc platform_mem_desc[] = {
{0x80000000,
0x80000000 + 0x7f000000,
0x80000000,
DDR_MEM},
{0, //< QSPI
0x1FFFFFFF,
0,
DEVICE_MEM},
{0x20000000, //<! LPC
0x27FFFFFF,
0x20000000,
DEVICE_MEM},
{FT_DEV_BASE_ADDR, //<! Device register
FT_DEV_END_ADDR,
FT_DEV_BASE_ADDR,
DEVICE_MEM},
{0x30000000, //<! debug
0x39FFFFFF,
0x30000000,
DEVICE_MEM},
{0x3A000000, //<! Internal register space in the on-chip network
0x3AFFFFFF,
0x3A000000,
DEVICE_MEM},
{FT_PCI_CONFIG_BASEADDR,
FT_PCI_CONFIG_BASEADDR + FT_PCI_CONFIG_REG_LENGTH,
FT_PCI_CONFIG_BASEADDR,
DEVICE_MEM},
{FT_PCI_IO_CONFIG_BASEADDR,
FT_PCI_IO_CONFIG_BASEADDR + FT_PCI_IO_CONFIG_REG_LENGTH,
FT_PCI_IO_CONFIG_BASEADDR,
DEVICE_MEM},
{FT_PCI_MEM32_BASEADDR,
FT_PCI_MEM32_BASEADDR + FT_PCI_MEM32_REG_LENGTH,
FT_PCI_MEM32_BASEADDR,
DEVICE_MEM},
};
const rt_uint32_t platform_mem_desc_size = sizeof(platform_mem_desc) / sizeof(platform_mem_desc[0]);
rt_uint32_t platform_get_gic_dist_base(void)
{
return FT_GICV3_DISTRIBUTOR_BASEADDRESS;
}
static rt_uint32_t timerStep;
void rt_hw_timer_isr(int vector, void *parameter)
{
gtimer_set_load_value(timerStep);
rt_tick_increase();
}
int rt_hw_timer_init(void)
{
rt_hw_interrupt_install(30, rt_hw_timer_isr, RT_NULL, "tick");
rt_hw_interrupt_umask(30);
timerStep = gtimer_get_counter_frequency();
timerStep /= RT_TICK_PER_SECOND;
gtimer_set_load_value(timerStep);
gtimer_set_control(1);
return 0;
}
INIT_BOARD_EXPORT(rt_hw_timer_init);
static void AssertCallback(const char *File, s32 Line)
{
Ft_printf("Assert Error is %s : %d \r\n", File, Line);
}
#ifdef RT_USING_SMP
void rt_hw_ipi_handler_install(int ipi_vector, rt_isr_handler_t ipi_isr_handler);
#endif
/**
* This function will initialize hardware board
*/
void rt_hw_board_init(void)
{
/* bsp debug */
FCpu_SpinLockInit();
Ft_GenericTimer_Init(0, RT_NULL);
Ft_vsprintfRegister((vsprintf_p)rt_vsprintf);
Ft_assertSetCallBack((Ft_assertCallback)AssertCallback);
/* interrupt init */
arm_gic_redist_address_set(0, FT_GICV3_RD_BASEADDRESS + 0, 0);
#if RT_CPUS_NR == 2
Ft_printf("arm_gic_redist_address_set is 2 \r\n");
arm_gic_redist_address_set(0, FT_GICV3_RD_BASEADDRESS + (2U << 16), 1);
#elif RT_CPUS_NR == 3
arm_gic_redist_address_set(0, FT_GICV3_RD_BASEADDRESS + (2U << 16), 1);
arm_gic_redist_address_set(0, FT_GICV3_RD_BASEADDRESS + 2 * (2U << 16), 2);
#elif RT_CPUS_NR == 4
arm_gic_redist_address_set(0, FT_GICV3_RD_BASEADDRESS + (2U << 16), 1);
arm_gic_redist_address_set(0, FT_GICV3_RD_BASEADDRESS + 2 * (2U << 16), 2);
arm_gic_redist_address_set(0, FT_GICV3_RD_BASEADDRESS + 3 * (2U << 16), 3);
#endif
rt_hw_interrupt_init();
rt_components_board_init();
rt_console_set_device(RT_CONSOLE_DEVICE_NAME);
/* 初始化内存池 */
#ifdef RT_USING_HEAP
rt_system_heap_init(HEAP_BEGIN, HEAP_END);
#endif
#ifdef RT_USING_SMP
/* install IPI handle */
rt_hw_interrupt_set_priority(RT_SCHEDULE_IPI, 16);
rt_hw_ipi_handler_install(RT_SCHEDULE_IPI, rt_scheduler_ipi_handler);
rt_hw_interrupt_umask(RT_SCHEDULE_IPI);
#endif
}
static void ft_reset(void)
{
FPsci_Reset();
}
MSH_CMD_EXPORT_ALIAS(ft_reset, ft_reset, ft_reset);
/*@}*/

View File

@ -0,0 +1,29 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2013-07-06 Bernard the first version
*/
#ifndef __BOARD_H__
#define __BOARD_H__
#include "ft_parameters.h"
#include "ft2004.h"
#if defined(__CC_ARM)
extern int Image$$RW_IRAM1$$ZI$$Limit;
#define HEAP_BEGIN ((void *)&Image$$RW_IRAM1$$ZI$$Limit)
#elif defined(__GNUC__)
extern int __bss_end;
#define HEAP_BEGIN ((void *)&__bss_end)
#endif
#define HEAP_END (void *)(0x80000000 + 1024 * 1024 * 1024)
void rt_hw_board_init(void);
#endif

View File

@ -0,0 +1,270 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2021-05-11 Carl the first version
*/
#include "drv_can.h"
#include "interrupt.h"
#include <string.h>
#ifdef BSP_USE_CAN
#define LOG_TAG "drv_can"
#include <drv_log.h>
#define _CAN0_NAME "can0"
#define _CAN1_NAME "can1"
#define RTHW_CAN_WAIT(_can) rt_sem_take(&_can->recv_semaphore, RT_WAITING_FOREVER);
#define RTHW_CAN_SEND(_can) rt_sem_release(&_can->recv_semaphore);
#ifdef BSP_USING_CAN0
struct ft2004_can drv_can0 =
{
.name = _CAN0_NAME,
.can_handle.Config.InstanceId = 0};
#endif
#ifdef BSP_USING_CAN1
struct ft2004_can drv_can1 =
{
.name = _CAN1_NAME,
.can_handle.Config.InstanceId = 1};
#endif
static void _can_recv_irq(void *args)
{
struct ft2004_can *drv_can = (struct ft2004_can *)args;
RTHW_CAN_SEND(drv_can);
}
static void rt_hw_inner_can_isr(int irqno, void *param)
{
FCan_IntrHandler(param);
}
static rt_err_t _can_config(struct rt_can_device *can, struct can_configure *cfg)
{
struct FCan_Bittiming bit_timing = {0};
struct ft2004_can *drv_can;
RT_ASSERT(can);
RT_ASSERT(cfg);
drv_can = (struct ft2004_can *)can->parent.user_data;
RT_ASSERT(drv_can);
FCan_CfgInitialize(&drv_can->can_handle, FCan_LookupConfig(drv_can->can_handle.Config.InstanceId));
FCan_SetHandler(&drv_can->can_handle, FCAN_HANDLER_RECV, _can_recv_irq, drv_can);
bit_timing.bitrate = cfg->baud_rate;
if (FCan_CalcBittiming(&bit_timing) != FCAN_SUCCESS)
{
LOG_E("Setting baud rate %x is not valid \r\n", bit_timing.bitrate);
return -RT_ERROR;
}
FCan_SetTiming(&drv_can->can_handle, &bit_timing);
rt_hw_interrupt_set_priority(drv_can->can_handle.Config.IrqNum, 16);
rt_hw_interrupt_install(drv_can->can_handle.Config.IrqNum, rt_hw_inner_can_isr, &drv_can->can_handle, drv_can->name);
rt_hw_interrupt_umask(drv_can->can_handle.Config.IrqNum);
FCan_Enable(&drv_can->can_handle);
return RT_EOK;
}
static rt_err_t _can_control(struct rt_can_device *can, int cmd, void *arg)
{
return RT_EOK;
}
static int _can_sendmsg(struct rt_can_device *can, const void *buf, rt_uint32_t box_num)
{
struct ft2004_can *drv_can;
struct rt_can_msg *pmsg = (struct rt_can_msg *)buf;
struct FCan_Frame can_frame = {0};
RT_ASSERT(can);
drv_can = (struct ft2004_can *)can->parent.user_data;
RT_ASSERT(drv_can);
/* Check the parameters */
RT_ASSERT(pmsg->len <= 8U);
if (RT_CAN_STDID == pmsg->ide)
{
can_frame.CanId = pmsg->id;
}
else
{
can_frame.CanId = pmsg->id;
can_frame.CanId |= CAN_EFF_FLAG;
}
if (RT_CAN_DTR == pmsg->rtr)
{
}
else
{
can_frame.CanId |= CAN_RTR_FLAG;
}
can_frame.CanDlc = pmsg->len & 0x0FU;
memcpy(can_frame.data, pmsg->data, 8);
return (FCan_SendByIrq(&drv_can->can_handle, &can_frame, 1, RT_NULL) == 1) ? RT_EOK : -RT_ERROR;
}
static int _can_recvmsg(struct rt_can_device *can, void *buf, rt_uint32_t fifo)
{
struct ft2004_can *drv_can;
struct rt_can_msg *pmsg = (struct rt_can_msg *)buf;
RT_ASSERT(can);
struct FCan_Frame recv_frame = {0};
drv_can = (struct ft2004_can *)can->parent.user_data;
RT_ASSERT(drv_can);
RTHW_CAN_WAIT(drv_can);
if (FCan_RecvByIrq(&drv_can->can_handle, &recv_frame, 1) == 0)
{
LOG_E("rx msg is error");
return -RT_ERROR;
}
if (CAN_EFF_FLAG & recv_frame.CanId)
{
pmsg->ide = RT_CAN_EXTID;
pmsg->id = (recv_frame.CanId & ~(RT_CAN_EXTID));
}
else
{
pmsg->ide = RT_CAN_STDID;
pmsg->id = recv_frame.CanId;
}
if (CAN_RTR_FLAG & recv_frame.CanId)
{
pmsg->id &= ~CAN_RTR_FLAG;
pmsg->rtr = RT_CAN_RTR;
}
else
{
pmsg->rtr = RT_CAN_DTR;
}
/* get len */
pmsg->len = recv_frame.CanDlc;
return RT_EOK;
}
static const struct rt_can_ops _can_ops =
{
_can_config,
_can_control,
_can_sendmsg,
_can_recvmsg,
};
int rt_hw_can_init(void)
{
#ifdef BSP_USING_CAN0
drv_can0.can_handle.Config.InstanceId = 0;
rt_sem_init(&drv_can0.recv_semaphore, "can0_recv", 0, RT_IPC_FLAG_FIFO);
drv_can0.device.config.ticks = 20000;
drv_can0.device.config.baud_rate = 1000000;
rt_hw_can_register(&drv_can0.device,
drv_can0.name,
&_can_ops,
&drv_can0);
#endif
#ifdef BSP_USING_CAN1
drv_can1.can_handle.Config.InstanceId = 1;
drv_can0.device.config.baud_rate = 1000000;
rt_sem_init(&drv_can1.recv_semaphore, "can1_recv", 0, RT_IPC_FLAG_FIFO);
rt_hw_can_register(&drv_can1.device,
drv_can1.name,
&_can_ops,
&drv_can1);
#endif
return 0;
}
INIT_BOARD_EXPORT(rt_hw_can_init);
#ifdef BSP_USING_CAN0_DEBUG
struct can_test_struct
{
const char *name;
struct rt_can_filter_config *filter;
rt_device_t candev;
struct rt_semaphore _sem;
};
static struct can_test_struct can0_test_obj = {
.name = _CAN0_NAME};
void can_recv_irq(void *param)
{
struct can_test_struct *_can_obj = (struct can_test_struct *)param;
rt_kprintf("can_recv_iqr \r\n");
rt_sem_release(&_can_obj->_sem);
}
static void rt_can_test_loopback_thread_entry(void *param)
{
struct can_test_struct *_can_obj = (struct can_test_struct *)param;
struct FCan_Frame recv_frame;
struct ft2004_can *drv_can;
rt_uint32_t i;
_can_obj->candev = rt_device_find(_can_obj->name);
RT_ASSERT(_can_obj->candev);
drv_can = (struct ft2004_can *)_can_obj->candev->user_data;
rt_sem_init(&_can_obj->_sem, "canrx_wait", 0, RT_IPC_FLAG_FIFO);
rt_device_open(_can_obj->candev, RT_DEVICE_OFLAG_RDWR);
while (1)
{
rt_kprintf(" start to wait loopback \r\n");
RTHW_CAN_WAIT(drv_can);
while (0 != FCan_RecvByIrq(&drv_can->can_handle, &recv_frame, 1))
{
rt_kprintf("CanId %x \r\n", recv_frame.CanId);
rt_kprintf("CanDlc %x \r\n", recv_frame.CanDlc);
for (i = 0; i < recv_frame.CanDlc; i++)
{
rt_kprintf("data [%d] %x \r\n", i, recv_frame.data[i]);
}
FCan_SendByIrq(&drv_can->can_handle, &recv_frame, 1, RT_NULL);
}
}
}
int rt_can0_test(void)
{
rt_thread_t tid;
tid = rt_thread_create("can0_loopback",
rt_can_test_loopback_thread_entry, &can0_test_obj,
1024, 16, 20);
if (tid != RT_NULL)
rt_thread_startup(tid);
return 0;
}
INIT_APP_EXPORT(rt_can0_test);
#endif
#endif

View File

@ -0,0 +1,38 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2021-05-11 Carl the first version
*/
#ifndef __DRV_CAN_H__
#define __DRV_CAN_H__
#ifdef __cplusplus
extern "C"
{
#endif
#include <board.h>
#include <rtdevice.h>
#include <rtthread.h>
#include "ft_can.h"
struct ft2004_can
{
const char *name;
FCan_t can_handle;
struct rt_semaphore recv_semaphore;
struct rt_can_device device; /* inherit from can device */
};
int rt_hw_can_init(void);
#ifdef __cplusplus
}
#endif
#endif // !

View File

@ -0,0 +1,691 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2021-03-09 Carl the first version
*/
#include "board.h"
#include <netif/ethernetif.h>
#include "lwipopts.h"
#include "ft_parameters.h"
#include "ft_gmac.h"
#include "ft_cache.h"
#include "ft_gmac_hw.h"
#include "ft_status.h"
#include "ft_io.h"
#include "drv_eth.h"
#ifdef BSP_USING_GMAC
#define LOG_TAG "drv.gmac"
#include <drv_log.h>
#define MAX_ADDR_LEN 6
#define LINK_THREAD_STACK_LENGTH 0x400
struct drv_gmac
{
struct eth_device parent; /* inherit from ethernet device */
Ft_Gmac_t Gmac; /* Gmac driver */
#ifndef PHY_USING_INTERRUPT_MODE
rt_timer_t poll_link_timer;
#endif
rt_uint8_t *rx_buffer; /* Buffer for RxDesc */
rt_uint8_t *tx_buffer; /* Buffer for TxDesc */
uint32_t eth_speed; /* eth_speed */
uint32_t eth_mode; /* ETH_Duplex_Mode */
rt_uint8_t dev_addr[MAX_ADDR_LEN]; /* MAC address */
struct rt_event link_event;
struct rt_thread _link_thread;
rt_uint8_t _link_thread_stack[LINK_THREAD_STACK_LENGTH];
rt_thread_t _debug_tid;
};
static void rt_ft2004_status_check(void *Args, u32 MacPhyStatus);
//
#if defined(RAW_DATA_PRINT)
#if defined(ETH_RX_DUMP) || defined(ETH_TX_DUMP)
#define __is_print(ch) ((unsigned int)((ch) - ' ') < 127u - ' ')
static void dump_hex(const rt_uint8_t *ptr, rt_size_t buflen)
{
unsigned char *buf = (unsigned char *)ptr;
int i, j;
for (i = 0; i < buflen; i += 16)
{
rt_kprintf("%08X: ", i);
for (j = 0; j < 16; j++)
if (i + j < buflen)
rt_kprintf("%02X ", buf[i + j]);
else
rt_kprintf(" ");
rt_kprintf(" ");
for (j = 0; j < 16; j++)
if (i + j < buflen)
rt_kprintf("%c", __is_print(buf[i + j]) ? buf[i + j] : '.');
rt_kprintf("\n");
}
}
#endif
#endif
/**
* @name: rt_gmacmem_create
* @msg: Initialize the Gmac TX/Rx Describe Memory
* @param {*}
* @return {*}
*/
static void rt_gmacmem_create(struct drv_gmac *pOsGmac)
{
pOsGmac->rx_buffer = rt_calloc(1, RX_DESCNUM * GMAC_MAX_PACKET_SIZE);
if (pOsGmac->rx_buffer == NULL)
{
LOG_E("rx_buffer Malloc is error ");
RT_ASSERT(0)
}
pOsGmac->tx_buffer = rt_calloc(1, TX_DESCNUM * GMAC_MAX_PACKET_SIZE);
if (pOsGmac->tx_buffer == NULL)
{
LOG_E("tx_buffer Malloc is error ");
RT_ASSERT(0)
}
pOsGmac->Gmac.TxDesc = rt_calloc(1, TX_DESCNUM * sizeof(FGmac_DmaDesc_t));
if (pOsGmac->Gmac.TxDesc == NULL)
{
LOG_E("TxDesc Malloc is error ");
RT_ASSERT(0)
}
pOsGmac->Gmac.RxDesc = rt_calloc(1, RX_DESCNUM * sizeof(FGmac_DmaDesc_t) + 128);
if (pOsGmac->Gmac.RxDesc == NULL)
{
LOG_E("RxDesc Malloc is error ");
RT_ASSERT(0)
}
#define ROUND_UP(x, align) (((long)(x) + ((long)align - 1)) & \
~((long)align - 1))
pOsGmac->Gmac.RxDesc = (FGmac_DmaDesc_t *)ROUND_UP(pOsGmac->Gmac.RxDesc, 128);
LOG_D("RxDesc fit after addr %x ", pOsGmac->Gmac.RxDesc);
}
static void rt_gmacmem_free(struct drv_gmac *pOsGmac)
{
if (pOsGmac->rx_buffer)
{
rt_free(pOsGmac->rx_buffer);
}
if (pOsGmac->tx_buffer)
{
rt_free(pOsGmac->tx_buffer);
}
if (pOsGmac->Gmac.RxDesc)
{
rt_free(pOsGmac->Gmac.RxDesc);
}
if (pOsGmac->Gmac.TxDesc)
{
rt_free(pOsGmac->Gmac.TxDesc);
}
}
static void rt_hw_gmac_isr(int irqno, void *param)
{
FGmac_IntrHandler(param);
}
static void rt_hw_gmac_recv_isr(void *Args)
{
struct drv_gmac *pOsMac;
rt_err_t result = 0;
if (RT_NULL == Args)
{
LOG_E("Args is NULL");
return;
}
pOsMac = (struct drv_gmac *)Args;
result = eth_device_ready(&(pOsMac->parent));
if (result != RT_EOK)
{
LOG_I("RxCpltCallback err = %d", result);
}
}
static rt_err_t
rt_ft2004_gmac_start(struct drv_gmac *pOsMac)
{
Ft_Gmac_t *pGmac;
pGmac = &pOsMac->Gmac;
if (FST_SUCCESS != Ft_Gmac_HwInitialize(pGmac))
{
return -RT_ERROR;
}
FGmac_SetHandler(pGmac, FT_GMAC_RX_COMPLETE_CB_ID, rt_hw_gmac_recv_isr, pOsMac);
FGmac_SetHandler(pGmac, FT_GMAC_MAC_PHY_STATUS_CB_ID, rt_ft2004_status_check, pOsMac);
/* Initialize Rx Description list : ring Mode */
FGmac_DmaRxDescRingInit(pGmac, pGmac->RxDesc, pOsMac->rx_buffer, GMAC_MAX_PACKET_SIZE, RX_DESCNUM);
/* Initialize Tx Description list : ring Mode */
FGmac_DmaTxDescRingInit(pGmac, pGmac->TxDesc, pOsMac->tx_buffer, GMAC_MAX_PACKET_SIZE, TX_DESCNUM);
Ft_Gmac_Start(pGmac);
/* Gmac interrupt init */
rt_hw_interrupt_install(pGmac->Config.IRQ_NUM, rt_hw_gmac_isr, pGmac, "Gmac");
rt_hw_interrupt_umask(pGmac->Config.IRQ_NUM);
return RT_EOK;
}
void rt_ft2004_gmac_stop(struct drv_gmac *pOsMac)
{
Ft_Gmac_t *pGmac;
pGmac = &pOsMac->Gmac;
Ft_Gmac_Stop(pGmac);
}
/* GMAC initialization function */
static rt_err_t rt_ft2004_gmac_init(rt_device_t dev)
{
struct drv_gmac *pOsMac;
struct eth_device *pGmacParent;
FGmac_Config_t *pConfig;
pGmacParent = rt_container_of(dev, struct eth_device, parent);
if (NULL == pGmacParent)
{
return -RT_ENOMEM;
}
pOsMac = rt_container_of(pGmacParent, struct drv_gmac, parent);
if (NULL == pOsMac)
{
return -RT_ENOMEM;
}
pConfig = Ft_Gmac_LookupConfig(pOsMac->Gmac.Config.InstanceId);
if (NULL == pConfig)
{
return -RT_ENOMEM;
}
Ft_Gmac_UseDefaultMacAddr(&pOsMac->Gmac, pOsMac->Gmac.Config.MacAddr);
if (FST_SUCCESS != Ft_GmacCfgInitialize(&pOsMac->Gmac, pConfig))
{
return -RT_ERROR;
}
return rt_ft2004_gmac_start(pOsMac);
}
static rt_err_t rt_ft2004_gmac_open(rt_device_t dev, rt_uint16_t oflag)
{
LOG_D("gmac open");
return RT_EOK;
}
static rt_err_t rt_ft2004_gmac_close(rt_device_t dev)
{
LOG_D("gmac close");
return RT_EOK;
}
static rt_size_t rt_ft2004_gmac_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size)
{
LOG_D("gmac read");
rt_set_errno(-RT_ENOSYS);
return 0;
}
static rt_size_t rt_ft2004_gmac_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size)
{
LOG_D("gmac write");
rt_set_errno(-RT_ENOSYS);
return 0;
}
static rt_err_t rt_ft2004_gmac_control(rt_device_t dev, int cmd, void *args)
{
struct drv_gmac *pOsMac;
struct eth_device *pGmacParent;
pGmacParent = rt_container_of(dev, struct eth_device, parent);
if (NULL == pGmacParent)
{
return -RT_ENOMEM;
}
pOsMac = rt_container_of(pGmacParent, struct drv_gmac, parent);
if (NULL == pOsMac)
{
return -RT_ENOMEM;
}
switch (cmd)
{
case NIOCTL_GADDR:
/* get mac address */
if (args)
rt_memcpy(args, pOsMac->dev_addr, 6);
else
return -RT_ERROR;
break;
default:
break;
}
return RT_EOK;
}
rt_err_t rt_ft2004_gmac_tx(rt_device_t dev, struct pbuf *p)
{
struct drv_gmac *pOsMac;
Ft_Gmac_t *pGmac;
struct eth_device *pGmacParent;
err_t errval;
struct pbuf *q;
u8 *Buffer = NULL;
volatile FGmac_DmaDesc_t *DmaTxDesc;
u32 FrameLength = 0;
u32 BufferOffset = 0;
u32 BytesLeftToCopy = 0;
u32 PayLoadOffset = 0;
pGmacParent = rt_container_of(dev, struct eth_device, parent);
if (NULL == pGmacParent)
{
return -RT_ENOMEM;
}
pOsMac = rt_container_of(pGmacParent, struct drv_gmac, parent);
if (NULL == pOsMac)
{
return -RT_ENOMEM;
}
pGmac = &pOsMac->Gmac;
DmaTxDesc = &pGmac->TxDesc[pGmac->TxDescRingData.DescBufIndex];
Buffer = (u8 *)DmaTxDesc->Buffer1Addr;
if (Buffer == NULL)
{
LOG_E("Buffer is NULL \r\n");
RT_ASSERT(0)
}
#if RT_LWIP_ETH_PAD_SIZE
pbuf_header(p, -RT_LWIP_ETH_PAD_SIZE); /* reclaim the padding word */
#endif
for (q = p; q != NULL; q = q->next)
{
/* Is this buffer available? If not, goto error */
if ((DmaTxDesc->Status & DMA_TDES0_OWN) != 0)
{
errval = ERR_USE;
LOG_E("error errval = ERR_USE; \r\n");
goto error;
}
/* Get bytes in current lwIP buffer */
BytesLeftToCopy = q->len;
PayLoadOffset = 0;
/* Check if the length of data to copy is bigger than Tx buffer size*/
while ((BytesLeftToCopy + BufferOffset) > GMAC_MAX_PACKET_SIZE)
{
/* Copy data to Tx buffer*/
memcpy((u8 *)((u8 *)Buffer + BufferOffset), (u8 *)((u8 *)q->payload + PayLoadOffset), (GMAC_MAX_PACKET_SIZE - BufferOffset));
FCache_cpuDcacheClean((rt_uint32_t *)DmaTxDesc->Buffer1Addr, GMAC_MAX_PACKET_SIZE);
GMAC_INC_DESC(pGmac->TxDescRingData.DescBufIndex, pGmac->TxDescRingData.DescMaxNumber);
/* Point to next descriptor */
DmaTxDesc = &pGmac->TxDesc[pGmac->TxDescRingData.DescBufIndex];
/* Check if the Bufferis available */
if ((DmaTxDesc->Status & DMA_TDES0_OWN) != (u32)0)
{
errval = ERR_USE;
LOG_E("Check if the Bufferis available \r\n");
goto error;
}
Buffer = (u8 *)(DmaTxDesc->Buffer1Addr);
BytesLeftToCopy = BytesLeftToCopy - (GMAC_MAX_PACKET_SIZE - BufferOffset);
PayLoadOffset = PayLoadOffset + (GMAC_MAX_PACKET_SIZE - BufferOffset);
FrameLength = FrameLength + (GMAC_MAX_PACKET_SIZE - BufferOffset);
BufferOffset = 0;
if (Buffer == NULL)
{
LOG_E(" error Buffer is 0 \r\n");
RT_ASSERT(0)
}
}
/* Copy the remaining bytes */
memcpy((u8 *)((u8 *)Buffer + BufferOffset), (u8 *)((u8 *)q->payload + PayLoadOffset), BytesLeftToCopy);
BufferOffset = BufferOffset + BytesLeftToCopy;
FrameLength = FrameLength + BytesLeftToCopy;
}
/* 指向下一个位置 */
FCache_cpuDcacheClean((rt_uint32_t *)DmaTxDesc->Buffer1Addr, GMAC_MAX_PACKET_SIZE);
GMAC_INC_DESC(pGmac->TxDescRingData.DescBufIndex, pGmac->TxDescRingData.DescMaxNumber);
#if RT_LWIP_ETH_PAD_SIZE
pbuf_header(p, RT_LWIP_ETH_PAD_SIZE); /* reclaim the padding word */
#endif
#ifdef ETH_TX_DUMP
dump_hex(Buffer, p->tot_len);
#endif
FGmac_TransmitframeRingPoll(pGmac, FrameLength);
error:
FGmac_SetTransmitUnderflow(pGmac);
return errval;
}
struct pbuf *rt_ft2004_gmac_rx(rt_device_t dev)
{
struct drv_gmac *pOsMac;
Ft_Gmac_t *pGmac;
struct eth_device *pGmacParent;
struct pbuf *p = NULL;
struct pbuf *q = NULL;
u16 Length = 0;
u8 *Buffer;
volatile FGmac_DmaDesc_t *DmaRxDesc;
u32 BufferOffset = 0;
u32 PayLoadOffset = 0;
u32 BytesLeftToCopy = 0;
u32 DescBufIndex; /* For Current Desc buffer buf position */
pGmacParent = rt_container_of(dev, struct eth_device, parent);
if (NULL == pGmacParent)
{
return RT_NULL;
}
pOsMac = rt_container_of(pGmacParent, struct drv_gmac, parent);
if (NULL == pOsMac)
{
return RT_NULL;
}
pGmac = &pOsMac->Gmac;
/* get received frame */
if (FST_SUCCESS != FGmac_RingGetReceivedFrame_IT(pGmac))
{
return NULL;
}
DescBufIndex = pGmac->RxDescRingData.DescBufIndex;
Length = (pGmac->RxDesc[DescBufIndex].Status & DMA_RDES0_FRAME_LEN_MASK) >> DMA_RDES0_FRAME_LEN_SHIFT;
Buffer = (u8 *)pGmac->RxDesc[DescBufIndex].Buffer1Addr;
#if RT_LWIP_ETH_PAD_SIZE
Length += RT_LWIP_ETH_PAD_SIZE; /* allow room for Ethernet padding */
#endif
if (Length > 0)
{
/* We allocate a pbuf chain of pbufs from the Lwip buffer pool */
p = pbuf_alloc(PBUF_RAW, Length, PBUF_POOL);
}
#ifdef ETH_RX_DUMP
dump_hex(Buffer, (u32)Length);
#endif
if (p != NULL)
{
#if RT_LWIP_ETH_PAD_SIZE
pbuf_header(p, -RT_LWIP_ETH_PAD_SIZE); /* drop the padding word */
#endif
DmaRxDesc = &pGmac->RxDesc[DescBufIndex];
BufferOffset = 0;
for (q = p; q != NULL; q = q->next)
{
BytesLeftToCopy = q->len;
PayLoadOffset = 0;
/* Check if the length of bytes to copy in current pbuf is bigger than Rx buffer size*/
while ((BytesLeftToCopy + BufferOffset) > GMAC_MAX_PACKET_SIZE)
{
/* Copy data to pbuf */
memcpy((u8 *)((u8 *)q->payload + PayLoadOffset), (u8 *)((u8 *)Buffer + BufferOffset), (GMAC_MAX_PACKET_SIZE - BufferOffset));
/* Point to next descriptor */
GMAC_INC_DESC(DescBufIndex, pGmac->RxDescRingData.DescMaxNumber);
if (DescBufIndex == pGmac->RxDescRingData.DescIndex)
{
break;
}
DmaRxDesc = &pGmac->RxDesc[DescBufIndex];
Buffer = (u8 *)(DmaRxDesc->Buffer1Addr);
BytesLeftToCopy = BytesLeftToCopy - (GMAC_MAX_PACKET_SIZE - BufferOffset);
PayLoadOffset = PayLoadOffset + (GMAC_MAX_PACKET_SIZE - BufferOffset);
BufferOffset = 0;
}
/* Copy remaining data in pbuf */
memcpy((u8 *)((u8 *)q->payload + PayLoadOffset), (u8 *)((u8 *)Buffer + BufferOffset), BytesLeftToCopy);
BufferOffset = BufferOffset + BytesLeftToCopy;
}
#if RT_LWIP_ETH_PAD_SIZE
pbuf_header(p, RT_LWIP_ETH_PAD_SIZE); /* reclaim the padding word */
#endif
}
/* Release descriptors to DMA */
/* Point to first descriptor */
DmaRxDesc = &pGmac->RxDesc[DescBufIndex];
/* Set Own bit in Rx descriptors: gives the buffers back to DMA */
for (DescBufIndex = pGmac->RxDescRingData.DescBufIndex; DescBufIndex != pGmac->RxDescRingData.DescIndex; GMAC_INC_DESC(DescBufIndex, pGmac->RxDescRingData.DescMaxNumber))
{
FCache_cpuDcacheInvalidate((rt_uint32_t *)pGmac->RxDesc[DescBufIndex].Buffer1Addr, GMAC_MAX_PACKET_SIZE);
DmaRxDesc->Status |= DMA_RDES0_OWN;
DmaRxDesc = &pGmac->RxDesc[DescBufIndex];
}
/* Sync index */
pGmac->RxDescRingData.DescBufIndex = pGmac->RxDescRingData.DescIndex;
FGmac_ResumeTransmissionReception(pGmac);
return p;
}
static void rt_ft2004_status_check(void *Args, u32 MacPhyStatus)
{
struct drv_gmac *pOsMac;
pOsMac = (struct drv_gmac *)Args;
if (MacPhyStatus & 0x8)
{
rt_event_send(&pOsMac->link_event, FT_NETIF_LINKUP);
}
else
{
rt_event_send(&pOsMac->link_event, FT_NETIF_DOWN);
}
}
static void ethernet_link_thread(void *Args)
{
struct drv_gmac *pOsMac;
rt_uint32_t status;
u32 LastStatus = FT_NETIF_DOWN;
u32 Flg;
if (RT_NULL == Args)
{
return;
}
pOsMac = (struct drv_gmac *)Args;
while (1)
{
status = 0;
if (rt_event_recv(&pOsMac->link_event, FT_NETIF_LINKUP | FT_NETIF_DOWN, RT_EVENT_FLAG_CLEAR | RT_EVENT_FLAG_OR,
RT_WAITING_FOREVER, &status) != RT_EOK)
{
LOG_E("wait completed timeout");
continue;
}
if (status & FT_NETIF_DOWN)
{
eth_device_linkchange(&pOsMac->parent, RT_FALSE);
LastStatus = FT_NETIF_DOWN;
}
else if (status & FT_NETIF_LINKUP)
{
Flg = (LastStatus == FT_NETIF_LINKUP) ? 0 : 1;
LastStatus = FT_NETIF_LINKUP;
}
else
{
LOG_I(" EventGroup is error \r\n");
RT_ASSERT(0)
}
if (Flg)
{
Flg = 0;
// eth_device_linkchange(&pOsMac->parent, RT_FALSE);
LOG_I(" Start Linkup \r\n");
rt_ft2004_gmac_stop(pOsMac);
rt_ft2004_gmac_start(pOsMac);
LOG_I(" HardWare is ok \r\n");
if (LastStatus == FT_NETIF_LINKUP)
{
rt_thread_mdelay(5000);
eth_device_linkchange(&pOsMac->parent, RT_TRUE);
}
}
}
}
#ifdef BSP_USING_GMAC0
struct drv_gmac os_drv_gmac0;
static char *os_drv_gmac0_name = "gmac0";
#endif
#ifdef BSP_USING_GMAC1
struct drv_gmac os_drv_gmac1;
static char *os_drv_gmac1_name = "gmac1";
#endif
static int rt_hw_gmac_init(struct drv_gmac *pOsMac, const char *name)
{
rt_err_t state = RT_EOK;
// rt_thread_t tid;
rt_gmacmem_free(pOsMac);
rt_gmacmem_create(pOsMac);
pOsMac->eth_speed = GMAC_SPEED_1000M;
pOsMac->eth_mode = GMAC_MODE_FULLDUPLEX;
pOsMac->parent.parent.init = rt_ft2004_gmac_init;
pOsMac->parent.parent.open = rt_ft2004_gmac_open;
pOsMac->parent.parent.close = rt_ft2004_gmac_close;
pOsMac->parent.parent.read = rt_ft2004_gmac_read;
pOsMac->parent.parent.write = rt_ft2004_gmac_write;
pOsMac->parent.parent.control = rt_ft2004_gmac_control;
pOsMac->parent.parent.user_data = RT_NULL;
pOsMac->parent.eth_rx = rt_ft2004_gmac_rx;
pOsMac->parent.eth_tx = rt_ft2004_gmac_tx;
Ft_Gmac_UseDefaultMacAddr(&pOsMac->Gmac, pOsMac->dev_addr);
state = rt_event_init(&pOsMac->link_event, name, RT_IPC_FLAG_FIFO);
LOG_I("rt_event_init is ok \r\n");
if (RT_EOK != state)
{
rt_kprintf("init gmac0 event failed.\n");
return -RT_ERROR;
}
/* register eth device */
state = eth_device_init(&(pOsMac->parent), name);
if (RT_EOK != state)
{
LOG_E("gmac device init faild: %d", state);
return -RT_ERROR;
}
state = rt_thread_init(&pOsMac->_link_thread,
name,
ethernet_link_thread,
pOsMac,
&pOsMac->_link_thread_stack[0],
sizeof(pOsMac->_link_thread_stack),
10, 2);
if (RT_EOK == state)
{
rt_thread_startup(&pOsMac->_link_thread);
}
else
{
LOG_E("rt_thread_init is error");
return -RT_ERROR;
}
return RT_EOK;
}
static int rt_hw_ft2004_eth_init(void)
{
rt_err_t state = RT_EOK;
#ifdef BSP_USING_GMAC0
os_drv_gmac0.Gmac.Config.InstanceId = 0;
state = rt_hw_gmac_init(&os_drv_gmac0, os_drv_gmac0_name);
if (RT_EOK != state)
{
goto __exit;
}
#endif
#ifdef BSP_USING_GMAC1
os_drv_gmac1.Gmac.Config.InstanceId = 1;
state = rt_hw_gmac_init(&os_drv_gmac1, os_drv_gmac1_name);
if (RT_EOK != state)
{
goto __exit;
}
#endif
__exit:
return state;
}
INIT_DEVICE_EXPORT(rt_hw_ft2004_eth_init);
#endif

View File

@ -0,0 +1,25 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2021-03-09 Carl the first version
*/
#ifndef __DRV_ETH_H__
#define __DRV_ETH_H__
#ifdef __cplusplus
extern "C"
{
#endif
#define FT_NETIF_LINKUP 0x1U
#define FT_NETIF_DOWN 0x2U
#ifdef __cplusplus
}
#endif
#endif // !

View File

@ -0,0 +1,27 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2018-11-15 SummerGift first version
*/
/*
* NOTE: DO NOT include this file on the header file.
*/
#ifndef LOG_TAG
#define DBG_TAG "drv"
#else
#define DBG_TAG LOG_TAG
#endif /* LOG_TAG */
#ifdef DRV_DEBUG
#define DBG_LVL DBG_LOG
#else
#define DBG_LVL DBG_INFO
#endif /* DRV_DEBUG */
#include <rtdbg.h>

View File

@ -0,0 +1,424 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2021-04-11 Carl the first version
*/
#include "drv_qspi.h"
#include <rtthread.h>
#include "rtdevice.h"
#include "ft_qspi.h"
#include "ft_parameters.h"
#ifdef BSP_USE_QSPI
#define DRV_DEBUG
#define LOG_TAG "drv.qspi"
#include <drv_log.h>
struct ft2004_qspi_bus
{
FQSpi_t fqspi;
char *name;
rt_uint32_t init; /* 1 is init already */
};
static struct rt_spi_bus _qspi_bus;
static struct ft2004_qspi_bus _ft2004_qspi_bus;
static int ft2004_qspi_init(struct rt_qspi_device *device, struct rt_qspi_configuration *qspi_cfg)
{
RT_ASSERT(device != RT_NULL);
RT_ASSERT(qspi_cfg != RT_NULL);
// struct rt_spi_configuration *cfg = &qspi_cfg->parent;
struct ft2004_qspi_bus *qspi_bus_p = device->parent.bus->parent.user_data;
if (qspi_bus_p->init == 0)
{
qspi_bus_p->init = 1;
FQSpi_CfgInitialize(&qspi_bus_p->fqspi, FQSpi_LookupConfig(0));
}
return RT_EOK;
}
static rt_err_t ft2004_cmdOperation(struct ft2004_qspi_bus *qspi_bus_p, struct rt_spi_message *message)
{
struct rt_qspi_message *qspi_message = (struct rt_qspi_message *)message;
const rt_uint8_t *sndb = message->send_buf;
rt_uint8_t *rcvb = message->recv_buf;
ft_error_t ret;
RT_ASSERT(qspi_bus_p != RT_NULL);
RT_ASSERT(message != RT_NULL);
struct FQSpi_CmdPack cmd_pack = {0};
if (qspi_message->instruction.qspi_lines == 0)
{
LOG_E("instruction is not valid");
return RT_ERROR;
}
cmd_pack.cmd = qspi_message->instruction.content;
if (qspi_message->address.qspi_lines != 0)
{
cmd_pack.flags |= FQSPI_CMD_NEED_ADDR_MASK;
cmd_pack.addr = qspi_message->address.content;
}
if (qspi_message->address.size == 24)
{
cmd_pack.flags |= FQSPI_CMD_ADDRESS_3BYTE_MASK;
}
else if (qspi_message->address.size == 32)
{
cmd_pack.flags |= FQSPI_CMD_ADDRESS_4BYTE_MASK;
}
if (qspi_message->qspi_data_lines != 0)
{
if (sndb && (message->length > 0))
{
cmd_pack.flags |= FQSPI_CMD_NEED_SET_MASK;
cmd_pack.txBuf = sndb;
cmd_pack.length = message->length;
}
else if (rcvb && (message->length > 0))
{
cmd_pack.flags |= FQSPI_CMD_NEED_GET_MASK;
cmd_pack.rxBuf = rcvb;
cmd_pack.length = message->length;
}
else
{
cmd_pack.flags &= ~(FQSPI_CMD_NEED_GET_MASK | FQSPI_CMD_NEED_SET_MASK);
}
}
if (qspi_message->dummy_cycles)
{
cmd_pack.flags |= FQSPI_CMD_NEED_DUMMY_MASK;
cmd_pack.dummyCycle = qspi_message->dummy_cycles;
}
if (cmd_pack.cmd == 0x20)
{
if (qspi_message->address.size == 32)
{
cmd_pack.cmd = 0xdc;
}
}
#ifdef BSP_QSPI_DEBUG
LOG_I("flags %x", cmd_pack.flags);
#endif
ret = FQSpi_CmdOperation(&qspi_bus_p->fqspi, &cmd_pack);
#ifdef BSP_QSPI_DEBUG
if (ret == FQSPI_SUCCESS)
if (cmd_pack.cmd == 5)
{
LOG_I("cmd05 0x%x", cmd_pack.rxBuf[0]);
}
#endif
return (ret == FQSPI_SUCCESS) ? RT_EOK : RT_ERROR;
}
static rt_uint32_t ft2004_qspi_xfer(struct ft2004_qspi_bus *qspi_bus_p, struct rt_spi_message *message)
{
struct rt_qspi_message *qspi_message = (struct rt_qspi_message *)message;
rt_uint32_t ret_length = 0;
const rt_uint8_t *sndb = message->send_buf;
rt_uint8_t *rcvb = message->recv_buf;
rt_int32_t length = message->length;
rt_uint32_t cmd;
rt_uint32_t addr;
FQSpi_t *qspi_p;
FQSpi_Config_t *qspi_config_p;
struct FQSpi_DataPack data_pack = {0};
qspi_p = &qspi_bus_p->fqspi;
qspi_config_p = &qspi_bus_p->fqspi.config;
cmd = qspi_message->instruction.content;
addr = qspi_message->address.content;
#ifdef BSP_QSPI_DEBUG
LOG_I("cmd is %x ", cmd);
LOG_I("length %d , rcvb %x sndb %x addr %x dummy_cycles %x ", length, rcvb, sndb, addr, qspi_message->dummy_cycles);
#endif
if (qspi_config_p->channel >= FT_QSPI_MAX_CS_NUM)
{
LOG_E("invalid channel[%x] ", qspi_config_p->channel);
return RT_ERROR;
}
switch (cmd)
{
case FQSPI_FLASH_CMD_PP:
{
if (RT_NULL != sndb)
{
data_pack.cmd = cmd;
data_pack.addr = addr;
if (qspi_message->address.size == 24)
{
data_pack.flags |= FQSPI_DATA_ADDRESS_3BYTE_MASK;
}
else
{
data_pack.flags |= FQSPI_DATA_ADDRESS_4BYTE_MASK;
}
LOG_E("write flags %x ", data_pack.flags);
data_pack.txBuf = sndb;
data_pack.length = length;
ret_length = ((FQSpi_Write(qspi_p, &data_pack) == FQSPI_SUCCESS) ? length : 0);
}
else
{
LOG_E("pp cmd %x sndb is null", cmd);
ret_length = 0;
}
}
break;
case FQSPI_FLASH_CMD_WRDI: /* for sufd qspi fast read */
FQSpi_FlashRegSet(qspi_p, cmd, RT_NULL, 0);
case FQSPI_FLASH_CMD_READ:
{
if (RT_NULL != rcvb)
{
data_pack.cmd = FQSPI_FLASH_CMD_READ;
data_pack.addr = addr;
if (qspi_message->address.size == 24)
{
data_pack.flags |= FQSPI_DATA_ADDRESS_3BYTE_MASK;
}
else
{
data_pack.flags |= FQSPI_DATA_ADDRESS_4BYTE_MASK;
}
if (qspi_message->dummy_cycles)
{
data_pack.flags |= FQSPI_DATA_NEED_DUMMY_MASK;
data_pack.dummyCycle = qspi_message->dummy_cycles;
}
data_pack.rxBuf = rcvb;
data_pack.length = length;
ret_length = ((FQSpi_Read(qspi_p, &data_pack) == FQSPI_SUCCESS) ? length : 0);
}
else
{
// LOG_E("read cmd %x rcvb is null", cmd);
ret_length = 0;
}
}
break;
default:
{
if (ft2004_cmdOperation(qspi_bus_p, message) == RT_EOK)
{
ret_length = 1;
}
else
{
LOG_E("ft2004_cmdOperation error");
ret_length = 0;
}
}
}
return ret_length;
}
static rt_uint32_t qspixfer(struct rt_spi_device *device, struct rt_spi_message *message)
{
RT_ASSERT(device != RT_NULL);
RT_ASSERT(device->bus != RT_NULL);
struct ft2004_qspi_bus *qspi_bus_p = device->bus->parent.user_data;
return ft2004_qspi_xfer(qspi_bus_p, message);
}
static rt_err_t qspi_configure(struct rt_spi_device *device, struct rt_spi_configuration *configuration)
{
RT_ASSERT(device != RT_NULL);
RT_ASSERT(configuration != RT_NULL);
struct rt_qspi_device *qspi_device = (struct rt_qspi_device *)device;
return ft2004_qspi_init(qspi_device, &qspi_device->config);
}
static const struct rt_spi_ops ft2004_qspi_ops =
{
.configure = qspi_configure,
.xfer = qspixfer,
};
static int ft2004_qspi_register_bus(struct ft2004_qspi_bus *qspi_bus, const char *name)
{
RT_ASSERT(qspi_bus != RT_NULL);
RT_ASSERT(name != RT_NULL);
_qspi_bus.parent.user_data = qspi_bus;
return rt_qspi_bus_register(&_qspi_bus, name, &ft2004_qspi_ops);
}
rt_err_t ft2004_qspi_bus_attach_device(const char *bus_name, const char *device_name, rt_uint8_t data_line_width, void (*enter_qspi_mode)(), void (*exit_qspi_mode)())
{
struct rt_qspi_device *qspi_device = RT_NULL;
rt_err_t result = RT_EOK;
RT_ASSERT(bus_name != RT_NULL);
RT_ASSERT(device_name != RT_NULL);
RT_ASSERT(data_line_width == 1 || data_line_width == 2 || data_line_width == 4);
qspi_device = (struct rt_qspi_device *)rt_malloc(sizeof(struct rt_qspi_device));
if (qspi_device == RT_NULL)
{
LOG_E("no memory, qspi bus attach device failed!");
result = RT_ENOMEM;
goto __exit;
}
qspi_device->enter_qspi_mode = enter_qspi_mode;
qspi_device->exit_qspi_mode = exit_qspi_mode;
qspi_device->config.qspi_dl_width = data_line_width;
result = rt_spi_bus_attach_device(&qspi_device->parent, device_name, bus_name, RT_NULL);
__exit:
if (result != RT_EOK)
{
if (qspi_device)
{
rt_free(qspi_device);
}
}
return result;
}
static int rt_hw_qspi_bus_init(void)
{
return ft2004_qspi_register_bus(&_ft2004_qspi_bus, FT2004_QSPI_NAME);
}
INIT_BOARD_EXPORT(rt_hw_qspi_bus_init);
#ifdef BSP_QSPI_DEBUG
static void cmd05_check(void)
{
struct FQSpi_CmdPack cmd_pack = {0};
u8 rx_buffer[1];
cmd_pack.cmd = 0x6;
FQSpi_CmdOperation(&_ft2004_qspi_bus.fqspi, &cmd_pack);
rt_memset(&cmd_pack, 0, sizeof(&cmd_pack));
cmd_pack.cmd = 0x5;
cmd_pack.flags = FQSPI_CMD_NEED_GET_MASK;
cmd_pack.rxBuf = rx_buffer;
cmd_pack.length = sizeof(rx_buffer);
FQSpi_CmdOperation(&_ft2004_qspi_bus.fqspi, &cmd_pack);
for (u32 i = 0; i < cmd_pack.length; i++)
{
LOG_I("cnt %d, 0x%x ", i, rx_buffer[i]);
}
rt_memset(&cmd_pack, 0, sizeof(&cmd_pack));
cmd_pack.cmd = 0x4;
FQSpi_CmdOperation(&_ft2004_qspi_bus.fqspi, &cmd_pack);
rt_memset(&cmd_pack, 0, sizeof(&cmd_pack));
cmd_pack.cmd = 0x5;
cmd_pack.flags = FQSPI_CMD_NEED_GET_MASK;
cmd_pack.rxBuf = rx_buffer;
cmd_pack.length = sizeof(rx_buffer);
FQSpi_CmdOperation(&_ft2004_qspi_bus.fqspi, &cmd_pack);
for (u32 i = 0; i < cmd_pack.length; i++)
{
LOG_I("cnt %d, 0x%x ", i, rx_buffer[i]);
}
}
MSH_CMD_EXPORT_ALIAS(cmd05_check, cmd05_check, cmd05_check);
#endif
#ifdef BSP_QSPI_DEBUG
static void cmd35_check(void)
{
struct FQSpi_CmdPack cmd_pack = {0};
u8 rx_buffer[1];
cmd_pack.cmd = 0x6;
FQSpi_CmdOperation(&_ft2004_qspi_bus.fqspi, &cmd_pack);
rt_memset(&cmd_pack, 0, sizeof(&cmd_pack));
cmd_pack.cmd = 0x5;
cmd_pack.flags = FQSPI_CMD_NEED_GET_MASK;
cmd_pack.rxBuf = rx_buffer;
cmd_pack.length = sizeof(rx_buffer);
FQSpi_CmdOperation(&_ft2004_qspi_bus.fqspi, &cmd_pack);
for (u32 i = 0; i < cmd_pack.length; i++)
{
LOG_I("cnt %d, 0x%x ", i, rx_buffer[i]);
}
cmd_pack.cmd = 0xB7;
FQSpi_CmdOperation(&_ft2004_qspi_bus.fqspi, &cmd_pack);
rt_memset(&cmd_pack, 0, sizeof(&cmd_pack));
cmd_pack.cmd = 0x35;
cmd_pack.flags = FQSPI_CMD_NEED_GET_MASK;
cmd_pack.rxBuf = rx_buffer;
cmd_pack.length = sizeof(rx_buffer);
FQSpi_CmdOperation(&_ft2004_qspi_bus.fqspi, &cmd_pack);
for (u32 i = 0; i < cmd_pack.length; i++)
{
LOG_I("cnt %d, 0x%x ", i, rx_buffer[i]);
}
}
MSH_CMD_EXPORT_ALIAS(cmd35_check, cmd35_check, cmd35_check);
#endif
#ifdef BSP_QSPI_DEBUG
static void cmd15_check(void)
{
struct FQSpi_CmdPack cmd_pack = {0};
u8 rx_buffer[1];
// cmd_pack.cmd = 0xB7;
// FQSpi_CmdOperation(&_ft2004_qspi_bus.fqspi, &cmd_pack);
rt_memset(&cmd_pack, 0, sizeof(&cmd_pack));
cmd_pack.cmd = 0x15;
cmd_pack.flags = FQSPI_CMD_NEED_GET_MASK;
cmd_pack.rxBuf = rx_buffer;
cmd_pack.length = sizeof(rx_buffer);
FQSpi_CmdOperation(&_ft2004_qspi_bus.fqspi, &cmd_pack);
for (u32 i = 0; i < cmd_pack.length; i++)
{
LOG_I("cnt %d, 0x%x ", i, rx_buffer[i]);
}
}
MSH_CMD_EXPORT_ALIAS(cmd15_check, cmd15_check, cmd15_check);
#endif
#endif

View File

@ -0,0 +1,29 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2021-04-11 Carl the first version
*/
#ifndef __DRT_QSPI_H__
#define __DRT_QSPI_H__
#include <rtthread.h>
#ifdef __cplusplus
extern "C"
{
#endif
#define FT2004_QSPI_NAME "qspi"
rt_err_t ft2004_qspi_bus_attach_device(const char *bus_name, const char *device_name, rt_uint8_t data_line_width, void (*enter_qspi_mode)(), void (*exit_qspi_mode)());
#ifdef __cplusplus
}
#endif
#endif // !DRT_QSPI_H

View File

@ -0,0 +1,39 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2021-04-08 Carl the first version
*/
#include <board.h>
#include <drv_qspi.h>
#include <rtdevice.h>
#include <rthw.h>
#include <finsh.h>
#ifdef BSP_USE_QSPI
#include "spi_flash.h"
#include "spi_flash_sfud.h"
#define _QSPI_DEVICE_NAME "qspiflash"
static int
rt_hw_qspi_flash_with_sfud_init(void)
{
ft2004_qspi_bus_attach_device(FT2004_QSPI_NAME, _QSPI_DEVICE_NAME, 1, RT_NULL, RT_NULL);
/* init gd */
rt_kprintf("start rt_sfud_flash_probe \r\n");
if (RT_NULL == rt_sfud_flash_probe("GD25LQ256D", _QSPI_DEVICE_NAME))
{
return -RT_ERROR;
}
return RT_EOK;
}
INIT_COMPONENT_EXPORT(rt_hw_qspi_flash_with_sfud_init);
#endif /* BSP_USING_QSPI_FLASH */

View File

@ -0,0 +1,154 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2021-03-18 Carl the first version
*/
#include <rtthread.h>
#ifdef BSP_USING_SDC
#include <dfs_elm.h>
#include <dfs_fs.h>
#include <dfs_posix.h>
#include "drv_sdctrl.h"
#define DBG_TAG "app.card"
#define DBG_LVL DBG_INFO
#include <rtdbg.h>
static rt_err_t _sdcard_mount(void)
{
rt_device_t device;
device = rt_device_find("sd0");
rt_kprintf("rt_device_find %x \r\n", device);
if (device == NULL)
{
mmcsd_wait_cd_changed(0);
ft2004_mmcsd_change();
if (mmcsd_wait_cd_changed(rt_tick_from_millisecond(5000)) == -RT_ETIMEOUT)
{
rt_kprintf("timeout \r\n");
return RT_ERROR;
}
device = rt_device_find("sd0");
}
rt_thread_mdelay(1000);
LOG_I("dfs_mount \r\n");
if (device != RT_NULL)
{
if (dfs_mount("sd0", "/", "elm", 0, 0) == RT_EOK)
{
LOG_I("sd card mount to '/'");
}
else
{
LOG_W("sd card mount to '/' failed!");
return RT_ERROR;
}
}
return RT_EOK;
}
static void _sdcard_unmount(void)
{
rt_thread_mdelay(200);
dfs_unmount("/");
LOG_I("Unmount \"/\"");
mmcsd_wait_cd_changed(0);
ft2004_mmcsd_change();
mmcsd_wait_cd_changed(rt_tick_from_millisecond(5000));
LOG_I("Unmount is over \r\n");
}
static void sd_mount(void *parameter)
{
rt_uint8_t state = 0; /* 1. is valid card ,0 is removal */
#ifdef BSP_SDC_IRQ_CARD_REMOVE
rt_uint32_t status;
#endif
while (1)
{
switch (state)
{
case 0:
if (ft2004_card_status() == 1)
{
#ifdef BSP_SDC_IRQ_CARD_REMOVE
ft2004_card_remove_check(0, RT_NULL); /* Clear removal flag bit */
#endif
if (_sdcard_mount() == RT_EOK)
{
state = 1;
}
else
{
/* For the critical case of frequent plug */
rt_kprintf("dfs_unmount \r\n");
_sdcard_unmount();
ft2004_sdctrl_reset();
}
}
else
{
rt_thread_mdelay(100);
}
break;
case 1:
#ifdef BSP_SDC_IRQ_CARD_REMOVE
if (ft2004_card_remove_check(RT_WAITING_FOREVER, &status) == RT_EOK)
{
if (status & SDCTR_CARD_REMOVE_FLG)
{
state = 0;
_sdcard_unmount();
}
}
#else
if (ft2004_card_status() == 0)
{
state = 0;
_sdcard_unmount();
}
#endif
else
{
rt_thread_mdelay(100);
}
break;
default:
state = 0;
break;
}
}
}
int ft2004_sdcard_mount(void)
{
rt_thread_t tid;
tid = rt_thread_create("sd_mount", sd_mount, RT_NULL,
8192, 2, 20);
if (tid != RT_NULL)
{
rt_thread_startup(tid);
}
else
{
LOG_E("create sd_mount thread err!");
}
return RT_EOK;
}
INIT_APP_EXPORT(ft2004_sdcard_mount);
#endif /* BSP_USING_SDCARD */

View File

@ -0,0 +1,659 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2021-03-18 Carl the first version
*/
#include "drv_sdctrl.h"
#include "ft_sdctrl_hw.h"
#include "ft_sdctrl.h"
#include "ft_debug.h"
#include "ft_types.h"
#include "ft_generic_timer.h"
#include <drivers/mmcsd_core.h>
#include "interrupt.h"
#include "rtconfig.h"
#include "ft_cache.h"
#ifdef BSP_USING_SDC
#define LOG_TAG "drv.sdmmc"
#include <drv_log.h>
#define RTHW_SDCTRL_LOCK(_sdctrl) rt_mutex_take(&_sdctrl->mutex, RT_WAITING_FOREVER)
#define RTHW_SDCTRL_UNLOCK(_sdctrl) rt_mutex_release(&_sdctrl->mutex);
struct mmcsd_pkg
{
struct rt_mmcsd_cmd *cmd;
void *buff;
rt_uint32_t flag;
};
typedef struct
{
FtsdCtrl_t ft_sdctrl;
struct rt_mmcsd_host *host;
struct rt_event event;
struct rt_mutex mutex;
struct mmcsd_pkg *pkg;
} ft_sdctrl_class_t;
ft_sdctrl_class_t sdctrl_class;
ALIGN(SDCTR_ALIGN_LEN)
static rt_uint8_t cache_buf[SDCTR_BUFF_SIZE];
static void rthw_sdctrl_send_command(ft_sdctrl_class_t *class_p, struct mmcsd_pkg *pkg);
static void demo_dump_sdc(void)
{
Ft_DumpHexWord((const rt_uint32_t *)(0x28207C00), 256);
}
MSH_CMD_EXPORT_ALIAS(demo_dump_sdc, dump_sdc, output all dump_sdc);
static void rthw_sdctrl_delay(u32 delayCnt)
{
Ft_GenericTimer_UsDelay(delayCnt);
}
static u32 rthw_sdctrl_rasp2type(u32 rasp)
{
switch (rasp)
{
case RESP_NONE:
return FTSDCTRL_CMD_RES_NONE;
case RESP_R2:
return FTSDCTRL_CMD_RES_LONG;
default:
return FTSDCTRL_CMD_RES_SHORT;
}
return FTSDCTRL_CMD_RES_SHORT;
}
static void rthw_sdctrl_transfer_by_dma(ft_sdctrl_class_t *class_p, struct mmcsd_pkg *pkg)
{
struct rt_mmcsd_data *data;
struct rt_mmcsd_cmd *cmd;
u32 rasp;
u32 *buff;
FtsdCtrl_t *ft_sdctrl_p;
if ((RT_NULL == class_p))
{
LOG_E("rthw_sdctrl_transfer_by_dma invalid class_p");
return;
}
ft_sdctrl_p = &class_p->ft_sdctrl;
if ((RT_NULL == pkg))
{
LOG_E("rthw_sdctrl_transfer_by_dma invalid args");
return;
}
data = pkg->cmd->data;
if (RT_NULL == data)
{
LOG_E("rthw_sdctrl_transfer_by_dma invalid args");
return;
}
buff = pkg->buff;
if (RT_NULL == buff)
{
LOG_E("rthw_sdctrl_transfer_by_dma invalid args");
return;
}
cmd = pkg->cmd;
rasp = resp_type(pkg->cmd);
rasp = rthw_sdctrl_rasp2type(rasp);
if (data->flags & DATA_DIR_WRITE)
{
#ifdef BSP_SDC_DEBUG_PRINT
rt_kprintf("DATA_DIR_WRITE %x \r\n", cmd->arg);
#endif
FCache_cpuDcacheClean(buff, data->blks * data->blksize);
/* data, card, blk: card : data + blk */
FSdCtrl_WriteData(ft_sdctrl_p, (UINTPTR)buff, cmd->arg, data->blks);
cmd->err = FSdCtrl_WaitCmdEnd(ft_sdctrl_p, (pFtsdCtrl_delayTimer_t)rthw_sdctrl_delay, rasp, cmd->resp);
#ifdef BSP_SDC_DEBUG_PRINT
for (int i = 0; i < 4; i++)
{
rt_kprintf("cmdRsp[%d] %x \r\n", i, cmd->resp[i]);
}
Ft_DumpHexWord(buff, 256);
#endif
FSdCtrl_WaitWriteDataEnd(ft_sdctrl_p, (pFtsdCtrl_delayTimer_t)rthw_sdctrl_delay, data->blks);
FCache_cpuDcacheInvalidate(buff, data->blks * data->blksize);
}
else if (data->flags & DATA_DIR_READ)
{
#ifdef BSP_SDC_DEBUG_PRINT
rt_kprintf("DATA_DIR_READ %x \r\n", cmd->arg);
#endif
if ((cmd->flags & CMD_ADTC) && (data->blksize < 512))
{
#ifdef BSP_SDC_DEBUG_PRINT
LOG_E("CMD_ADTC \r\n");
#endif
FSdCtrl_DoACmd(ft_sdctrl_p, cmd->cmd_code, rasp, cmd->arg);
rt_thread_mdelay(10);
}
FCache_cpuDcacheInvalidate(buff, data->blks * data->blksize);
FSdCtrl_ReadData(ft_sdctrl_p, (UINTPTR)buff, cmd->arg, data->blks);
cmd->err = FSdCtrl_WaitCmdEnd(ft_sdctrl_p, (pFtsdCtrl_delayTimer_t)rthw_sdctrl_delay, rasp, cmd->resp);
#ifdef BSP_SDC_DEBUG_PRINT
for (int i = 0; i < 4; i++)
{
rt_kprintf("cmdRsp[%d] %x \r\n", i, cmd->resp[i]);
}
#endif
FSdCtrl_WaitReadDataEnd(ft_sdctrl_p, (pFtsdCtrl_delayTimer_t)rthw_sdctrl_delay, data->blks);
FCache_cpuDcacheClean(buff, data->blks * data->blksize);
#ifdef BSP_SDC_DEBUG_PRINT
Ft_DumpHexWord(buff, data->blks * data->blksize);
#endif
}
}
static void rthw_sdctrl_docmd(ft_sdctrl_class_t *class_p, struct mmcsd_pkg *pkg)
{
struct rt_mmcsd_cmd *cmd;
u32 rasp;
FtsdCtrl_t *ft_sdctrl_p;
if ((RT_NULL == class_p))
{
LOG_E("rthw_sdctrl_docmd invalid class_p");
return;
}
ft_sdctrl_p = &class_p->ft_sdctrl;
if ((RT_NULL == pkg))
{
LOG_E("rthw_sdctrl_docmd invalid args");
return;
}
cmd = pkg->cmd;
rasp = resp_type(pkg->cmd);
rasp = rthw_sdctrl_rasp2type(rasp);
FSdCtrl_DoCmd(ft_sdctrl_p, pkg->cmd->cmd_code, rasp, cmd->arg);
cmd->err = FSdCtrl_WaitCmdEnd(ft_sdctrl_p, (pFtsdCtrl_delayTimer_t)rthw_sdctrl_delay, rasp, cmd->resp);
#ifdef BSP_SDC_DEBUG_PRINT
for (int i = 0; i < 4; i++)
{
rt_kprintf("cmdRsp[%d] %x \r\n", i, cmd->resp[i]);
}
#endif
}
static void rthw_sdctrl_send_command(ft_sdctrl_class_t *class_p, struct mmcsd_pkg *pkg)
{
struct rt_mmcsd_cmd *cmd = pkg->cmd;
struct rt_mmcsd_data *data = cmd->data;
/* save pkg */
class_p->pkg = pkg;
/* config data reg */
if (data != RT_NULL && data->blks)
{
/* transfer config */
rthw_sdctrl_transfer_by_dma(class_p, pkg);
}
else
{
rthw_sdctrl_docmd(class_p, pkg);
}
}
/**
* @brief This function send sdio request.
* @param host rt_mmcsd_host
* @param req request
* @retval None
*/
static void rthw_sdctrl_request(struct rt_mmcsd_host *host, struct rt_mmcsd_req *req)
{
struct mmcsd_pkg pkg;
ft_sdctrl_class_t *class_p = host->private_data;
struct rt_mmcsd_data *data;
RTHW_SDCTRL_LOCK(class_p);
if (req->cmd != RT_NULL)
{
rt_memset(&pkg, 0, sizeof(pkg));
data = req->cmd->data;
pkg.cmd = req->cmd;
if (pkg.cmd->cmd_code == 5 || pkg.cmd->cmd_code == 1)
{
rt_kprintf("cmd_code is not vaild %x \r\n", pkg.cmd->cmd_code);
pkg.cmd->err = RT_EINVAL;
goto _exit;
}
#ifdef BSP_SDC_DEBUG_PRINT
struct rt_mmcsd_cmd *cmd;
cmd = req->cmd;
LOG_E("CMD:%d ARG:0x%08x RES:%s%s%s%s%s%s%s%s%s rw:%c len:%d blksize:%d",
cmd->cmd_code,
cmd->arg,
resp_type(cmd) == RESP_NONE ? "NONE" : "",
resp_type(cmd) == RESP_R1 ? "R1" : "",
resp_type(cmd) == RESP_R1B ? "R1B" : "",
resp_type(cmd) == RESP_R2 ? "R2" : "",
resp_type(cmd) == RESP_R3 ? "R3" : "",
resp_type(cmd) == RESP_R4 ? "R4" : "",
resp_type(cmd) == RESP_R5 ? "R5" : "",
resp_type(cmd) == RESP_R6 ? "R6" : "",
resp_type(cmd) == RESP_R7 ? "R7" : "",
data ? (data->flags & DATA_DIR_WRITE ? 'w' : 'r') : '-',
data ? data->blks * data->blksize : 0,
data ? data->blksize : 0);
#endif
if (data != RT_NULL)
{
rt_uint32_t size = data->blks * data->blksize;
RT_ASSERT(size <= SDCTR_BUFF_SIZE);
pkg.buff = data->buf;
if ((rt_uint32_t)data->buf & (SDCTR_ALIGN_LEN - 1))
{
pkg.buff = cache_buf;
if (data->flags & DATA_DIR_WRITE)
{
rt_memcpy(cache_buf, data->buf, size);
}
}
}
rthw_sdctrl_send_command(class_p, &pkg);
if ((data != RT_NULL) && (data->flags & DATA_DIR_READ) && ((rt_uint32_t)data->buf & (SDCTR_ALIGN_LEN - 1)))
{
rt_memcpy(data->buf, cache_buf, data->blksize * data->blks);
}
}
if (req->stop != RT_NULL)
{
rt_memset(&pkg, 0, sizeof(pkg));
pkg.cmd = req->stop;
rthw_sdctrl_send_command(class_p, &pkg);
}
_exit:
RTHW_SDCTRL_UNLOCK(class_p);
mmcsd_req_complete(class_p->host);
}
static void rthw_sdctrl_clk_divider(struct rt_mmcsd_host *host, struct rt_mmcsd_io_cfg *io_cfg)
{
ft_sdctrl_class_t *class_p = host->private_data;
FtsdCtrl_t *sd_ctrl = &(class_p->ft_sdctrl);
/* bus mode is pull push */
FSdCtrl_ClkFreqSetup(sd_ctrl, io_cfg->clock);
return;
}
static void rthw_sdctrl_iocfg(struct rt_mmcsd_host *host, struct rt_mmcsd_io_cfg *io_cfg)
{
ft_sdctrl_class_t *class_p = host->private_data;
RTHW_SDCTRL_LOCK(class_p);
/* calculate and set clk divider */
rthw_sdctrl_clk_divider(host, io_cfg);
RTHW_SDCTRL_UNLOCK(class_p);
}
rt_int32_t rthw_sdctrl_detect(struct rt_mmcsd_host *host)
{
ft_sdctrl_class_t *class_p = host->private_data;
return FSdCtrl_CardDetect(&class_p->ft_sdctrl);
}
static const struct rt_mmcsd_host_ops ops =
{
rthw_sdctrl_request,
rthw_sdctrl_iocfg,
rthw_sdctrl_detect,
RT_NULL,
};
void rthw_sdctrl_nomarl_callback(void *args)
{
FtsdCtrl_t *pFtsdCtrl = (FtsdCtrl_t *)args;
rt_uint32_t status;
ft_sdctrl_class_t *class_p;
if (RT_NULL == pFtsdCtrl)
{
return;
}
class_p = rt_container_of(pFtsdCtrl, ft_sdctrl_class_t, ft_sdctrl);
status = FSdCtrl_GetNormalIrqStatus(pFtsdCtrl);
if (status & NORMAL_INT_STATUS_CR)
{
rt_event_send(&class_p->event, SDCTR_CARD_REMOVE_FLG);
}
else if (status & NORMAL_INT_STATUS_CC)
{
rt_event_send(&class_p->event, SDCTR_CMD_IS_COMPLETE_FLG);
}
else if (status & NORMAL_INT_STATUS_EI)
{
rt_event_send(&class_p->event, SDCTR_CMD_IS_ERROR_FLG);
}
return;
}
void rthw_sdctrl_dma_callback(void *args)
{
FtsdCtrl_t *pFtsdCtrl = (FtsdCtrl_t *)args;
rt_uint32_t status;
ft_sdctrl_class_t *class_p;
if (RT_NULL == pFtsdCtrl)
{
return;
}
class_p = rt_container_of(pFtsdCtrl, ft_sdctrl_class_t, ft_sdctrl);
status = FSdCtrl_GetDataIrqStatus(pFtsdCtrl);
if (status & BD_ISR_REG_TRS)
{
/* send write complete event */
rt_event_send(&class_p->event, SDCTR_WRITE_IS_COMPLETE_FLG);
}
if (status & BD_ISR_REG_RESPE)
{
/* send read complete event */
rt_event_send(&class_p->event, SDCTR_READ_IS_COMPLETE_FLG);
}
if (status & BD_ISR_REG_DAIS)
{
/* send dma errror event */
rt_event_send(&class_p->event, SDCTR_DMA_IS_ERROR_FLG);
}
}
void rthw_sdctrl_error_callback(void *args)
{
FtsdCtrl_t *pFtsdCtrl = (FtsdCtrl_t *)args;
rt_uint32_t status;
ft_sdctrl_class_t *class_p;
if (RT_NULL == pFtsdCtrl)
{
return;
}
class_p = rt_container_of(pFtsdCtrl, ft_sdctrl_class_t, ft_sdctrl);
status = FSdCtrl_GetErrorIrqStatus(pFtsdCtrl);
if (status & SDCTR_CMD_TIMEOUT_FLG)
{
rt_event_send(&class_p->event, SDCTR_CMD_TIMEOUT_FLG);
}
if (status & ERROR_INT_EN_CNR)
{
rt_event_send(&class_p->event, SDCTR_CMD_RECEIVE_IS_ERROR_FLG);
}
if (status & ERROR_INT_EN_CCRCE)
{
rt_event_send(&class_p->event, SDCTR_CMD_CRC_IS_ERROR_FLG);
}
}
void rthw_sdctrl_normal_irq(int vector, void *param)
{
FtsdCtrl_t *pFtsdCtrl = (FtsdCtrl_t *)param;
FSdCtrl_NormalIrq(pFtsdCtrl);
}
void rthw_sdctrl_dma_irq(int vector, void *param)
{
FtsdCtrl_t *pFtsdCtrl = (FtsdCtrl_t *)param;
FSdCtrl_DmaIrq(pFtsdCtrl);
}
void rthw_sdctrl_err_irq(int vector, void *param)
{
FtsdCtrl_t *pFtsdCtrl = (FtsdCtrl_t *)param;
FSdCtrl_ErrIrq(pFtsdCtrl);
}
ft_error_t rthw_sdctrl_cmd_wait(FtsdCtrl_t *pFtsdCtrl)
{
rt_uint32_t status;
ft_sdctrl_class_t *class_p;
if (RT_NULL == pFtsdCtrl)
{
return FTSDC_INVALID_PARAM;
}
class_p = rt_container_of(pFtsdCtrl, ft_sdctrl_class_t, ft_sdctrl);
if (rt_event_recv(&class_p->event, SDCTR_CMD_IS_COMPLETE_FLG | SDCTR_CMD_IS_ERROR_FLG | SDCTR_CMD_CRC_IS_ERROR_FLG, RT_EVENT_FLAG_CLEAR | RT_EVENT_FLAG_OR,
rt_tick_from_millisecond(50000), &status) != RT_EOK)
{
/* wait cmd completed timeout */
LOG_E("wait cmd completed timeout");
return FTSDC_TIMEOUT;
}
if (SDCTR_CMD_IS_COMPLETE_FLG == (status & SDCTR_CMD_IS_COMPLETE_FLG))
{
return FTSDC_SUCCESS;
}
else
{
LOG_E("wait cmd is error %x ", status);
return FTSDC_FAILURE;
}
}
ft_error_t rthw_sdctrl_read_wait(FtsdCtrl_t *pFtsdCtrl)
{
rt_uint32_t status;
ft_sdctrl_class_t *class_p;
if (RT_NULL == pFtsdCtrl)
{
return FTSDC_INVALID_PARAM;
}
class_p = rt_container_of(pFtsdCtrl, ft_sdctrl_class_t, ft_sdctrl);
if (rt_event_recv(&class_p->event, SDCTR_READ_IS_COMPLETE_FLG | SDCTR_CMD_RECEIVE_IS_ERROR_FLG,
RT_EVENT_FLAG_CLEAR | RT_EVENT_FLAG_OR,
rt_tick_from_millisecond(50000), &status) != RT_EOK)
{
/* wait read completed timeout */
LOG_E("wait read completed timeout");
return FTSDC_TIMEOUT;
}
if (SDCTR_READ_IS_COMPLETE_FLG == (status & SDCTR_READ_IS_COMPLETE_FLG))
{
return FTSDC_SUCCESS;
}
else
{
LOG_E("wait read is error %x ", status);
return FTSDC_FAILURE;
}
}
ft_error_t rthw_sdctrl_write_wait(FtsdCtrl_t *pFtsdCtrl)
{
rt_uint32_t status;
ft_sdctrl_class_t *class_p;
if (RT_NULL == pFtsdCtrl)
{
return FTSDC_INVALID_PARAM;
}
class_p = rt_container_of(pFtsdCtrl, ft_sdctrl_class_t, ft_sdctrl);
if (rt_event_recv(&class_p->event, SDCTR_WRITE_IS_COMPLETE_FLG, RT_EVENT_FLAG_CLEAR | RT_EVENT_FLAG_OR,
rt_tick_from_millisecond(50000), &status) != RT_EOK)
{
/* wait write completed timeout */
LOG_E("wait write completed timeout");
return FTSDC_TIMEOUT;
}
if (SDCTR_WRITE_IS_COMPLETE_FLG == (status & SDCTR_WRITE_IS_COMPLETE_FLG))
{
return FTSDC_SUCCESS;
}
else
{
LOG_E("wait write is error %x ", status);
return FTSDC_FAILURE;
}
}
static rt_err_t rthw_sdctrl_create(ft_sdctrl_class_t *class_p)
{
struct rt_mmcsd_host *host;
host = mmcsd_alloc_host();
if (host == RT_NULL)
{
LOG_E("L:%d F:%s mmcsd alloc host fail");
return RT_ENOMEM;
}
class_p->ft_sdctrl.config = *(FSdCtrl_Config_t *)FSdCtrl_LookupConfig(0);
rt_event_init(&class_p->event, "sdctrl", RT_IPC_FLAG_FIFO);
rt_mutex_init(&class_p->mutex, "sdctrl", RT_IPC_FLAG_FIFO);
class_p->host = host;
host->ops = &ops;
/* range of sd work speed */
host->freq_min = 400 * 1000;
host->freq_max = 48 * 1000000;
host->valid_ocr = 0X00FFFF80; /* The voltage range supported is 1.65v-3.6v */
host->flags = MMCSD_BUSWIDTH_4;
host->private_data = class_p;
/* ready to change */
return RT_EOK;
}
int rthw_sdctrl_init(void)
{
FtsdCtrl_t *ft_sdctrl_p;
#ifdef BSP_SDC_USE_IRQ
FSdCtrl_Config_t *config_p;
FSdCtrl_NormalIrqSelect_t normalIrqFlgs = 0;
#endif
rt_kprintf("rthw_sdctrl_init \r\n");
RT_ASSERT(rthw_sdctrl_create(&sdctrl_class) == RT_EOK);
ft_sdctrl_p = &sdctrl_class.ft_sdctrl;
FSdCtrl_Reset(ft_sdctrl_p, (pFtsdCtrl_delayTimer_t)rthw_sdctrl_delay);
FsdCtrl_Init(ft_sdctrl_p);
#ifdef BSP_SDC_USE_IRQ
config_p = &ft_sdctrl_p->config;
#ifdef BSP_SDC_IRQ_CARD_REMOVE
normalIrqFlgs |= NORMAL_IRQ_CR;
#endif
normalIrqFlgs |= NORMAL_IRQ_CC;
/* register handler、irq enable bit and wait callback */
FSdCtrl_SetHandler(ft_sdctrl_p, FTSDCTRL_CMDIRQID, rthw_sdctrl_nomarl_callback, ft_sdctrl_p);
FSdCtrl_NormalIrqSet(ft_sdctrl_p, normalIrqFlgs);
FSdCtrl_CmdWaitRegister(ft_sdctrl_p, rthw_sdctrl_cmd_wait);
FSdCtrl_SetHandler(ft_sdctrl_p, FTSDCTRL_DMADATAIRQID, rthw_sdctrl_dma_callback, ft_sdctrl_p);
FSdCtrl_BdIrqSet(ft_sdctrl_p, BD_IRQ_TRS | BD_IRQ_RESPE);
FSdCtrl_WriteWaitRegister(ft_sdctrl_p, rthw_sdctrl_write_wait);
FSdCtrl_ReadWaitRegister(ft_sdctrl_p, rthw_sdctrl_read_wait);
config_p->workMode = FTSDCTRL_CMD_IRQ_MASK | FTSDCTRL_DATA_WRITE_IRQ_MASK | FTSDCTRL_DATA_READ_IRQ_MASK;
#else
#endif
/* install normal irq */
rt_hw_interrupt_install(ft_sdctrl_p->config.normalIrqNum, rthw_sdctrl_normal_irq,
&sdctrl_class.ft_sdctrl, "normalIrq");
rt_hw_interrupt_umask(ft_sdctrl_p->config.normalIrqNum);
rt_hw_interrupt_install(ft_sdctrl_p->config.dmaIrqNum, rthw_sdctrl_dma_irq,
&sdctrl_class.ft_sdctrl, "dmaIrq");
rt_hw_interrupt_umask(ft_sdctrl_p->config.dmaIrqNum);
return 0;
}
INIT_DEVICE_EXPORT(rthw_sdctrl_init);
void ft2004_mmcsd_change(void)
{
mmcsd_change(sdctrl_class.host);
}
rt_bool_t ft2004_card_status(void)
{
return FSdCtrl_CardDetect(&sdctrl_class.ft_sdctrl);
}
rt_err_t ft2004_card_remove_check(rt_int32_t timeout, rt_uint32_t *status)
{
return rt_event_recv(&sdctrl_class.event, SDCTR_CARD_REMOVE_FLG, RT_EVENT_FLAG_CLEAR | RT_EVENT_FLAG_OR,
timeout, status);
}
void ft2004_sdctrl_reset(void)
{
FSdCtrl_Reset(&sdctrl_class.ft_sdctrl, (pFtsdCtrl_delayTimer_t)rthw_sdctrl_delay);
FsdCtrl_Init(&sdctrl_class.ft_sdctrl);
#ifdef BSP_SDC_USE_IRQ
FSdCtrl_NormalIrqSet(&sdctrl_class.ft_sdctrl, NORMAL_IRQ_CC | NORMAL_IRQ_CR | NORMAL_IRQ_EI);
FSdCtrl_BdIrqSet(&sdctrl_class.ft_sdctrl, BD_IRQ_TRS | BD_IRQ_RESPE);
#endif
}
#endif

View File

@ -0,0 +1,47 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2021-03-18 Carl the first version
*/
#ifndef __DRV_SDCTRL_H__
#define __DRV_SDCTRL_H__
#include <rtthread.h>
#ifdef __cplusplus
extern "C"
{
#endif
#define SDCTR_CMD_IS_COMPLETE_FLG 0x1UL /* Command is complete */
#define SDCTR_WRITE_IS_COMPLETE_FLG 0x2UL
#define SDCTR_READ_IS_COMPLETE_FLG 0x4UL
#define SDCTR_CMD_IS_ERROR_FLG 0x8UL
#define SDCTR_CMD_CRC_IS_ERROR_FLG 0x10UL /* Command CRC error */
#define SDCTR_DMA_IS_ERROR_FLG 0x20UL /* */
#define SDCTR_CARD_REMOVE_FLG 0x40UL /* Card remove */
#define SDCTR_CMD_TIMEOUT_FLG 0x70UL /* command timeout */
#define SDCTR_CMD_RECEIVE_IS_ERROR_FLG 0x80UL /* CMD receive is error */
#ifndef SDCTR_BUFF_SIZE
#define SDCTR_BUFF_SIZE (512 * 128)
#endif
#ifndef SDCTR_ALIGN_LEN
#define SDCTR_ALIGN_LEN (32)
#endif
void ft2004_mmcsd_change(void);
rt_bool_t ft2004_card_status(void);
rt_err_t ft2004_card_remove_check(rt_int32_t timeout, rt_uint32_t *status);
void ft2004_sdctrl_reset(void);
#ifdef __cplusplus
}
#endif
#endif // !

View File

@ -0,0 +1,449 @@
/*
 * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
 *
 * SPDX-License-Identifier: Apache-2.0.
 *
* @Date: 2021-04-25 14:01:29
* @LastEditTime: 2021-05-26 15:42:52
* @Description:  This files is for
*
* @Modify History:
* Ver   Who        Date         Changes
* ----- ------     --------    --------------------------------------
*/
#include "drv_spi.h"
#include <rtthread.h>
#include <rtdevice.h>
#include <string.h>
#include "ft_spi.h"
#include "ft_mux.h"
#include "ft_trace.h"
#include "ft_generic_timer.h"
#ifdef BSP_USE_SPI
#define DRV_DEBUG
#define LOG_TAG "drv.spi"
#include <drv_log.h>
typedef void (*spi_cs_handler_t)(const rt_bool_t select);
typedef struct
{
FSpi_Ctrl_t spi_ctrl;
struct rt_spi_bus spi_bus;
uint16_t spi_cs_pin;
spi_cs_handler_t spi_cs_handler;
} ft2004_spi_class;
void ft2004_spi_cs(const rt_bool_t select);
static ft2004_spi_class spi_obj = {
.spi_cs_handler = ft2004_spi_cs,
.spi_ctrl = {
.CtrlId = SPI_CTRL_ID_0,
.DevId = SPI_DEV_ID_0,
.IsReady = FALSE,
.CsPin = 5, /* use pin 5 in gpio group a as cs signal pin */
},
};
static const FSpi_Conf_t spi_conf[NUM_OF_SPI_CTRL] =
{
{
.DevAddr = {0x00, 0x00, 0x00, 0x00},
.DevAddrLen = SPI_4_BYTE_ADDR,
.WorkMode = SPI_CTRL_MASTER_MODE,
/* mode 2 CPOL = 1, CPHA = 0 */
.Cpol = SPI_CTRL_CPOL_HIGH,
.Cpha = SPI_CTRL_CPHA_1EDGE,
.BaudRDiv = SPI_SCKDV_4,
},
{
.DevAddr = {0x00, 0x00, 0x00, 0x00},
.DevAddrLen = SPI_4_BYTE_ADDR,
.WorkMode = SPI_CTRL_MASTER_MODE,
.Cpol = SPI_CTRL_CPOL_HIGH,
.Cpha = SPI_CTRL_CPHA_1EDGE,
.BaudRDiv = SPI_SCKDV_MAX,
}};
inline static ft2004_spi_class *ft2004_spi_get_class()
{
return &spi_obj;
}
inline static FSpi_Ctrl_t *ft2004_spi_get_ctrl()
{
return &(ft2004_spi_get_class()->spi_ctrl);
}
static const FSpi_Conf_t *ft2004_lookup_conf(FT_IN FSpi_CtrlId_t CtrlId)
{
return &spi_conf[CtrlId];
}
void ft2004_spi_cs(const rt_bool_t select)
{
FSpi_Ctrl_t *ctrl_p = ft2004_spi_get_ctrl();
FSpi_SelectSlave(ctrl_p, ctrl_p->DevId, (bool_t)select);
}
/**spi flash operations***/
u32 ft2004_spi_transcation(const u8 tx_data, u8 *rx_data_p)
{
FSpi_Ctrl_t *ctrl_p = ft2004_spi_get_ctrl();
u32 ret = ERR_SPI_OK;
ret = FSpi_ReadWriteByte(ctrl_p, tx_data, rx_data_p);
return ret;
}
/**spi flash operations***/
static rt_err_t ft2004_spi_init(struct rt_spi_configuration *cfg)
{
FSpi_Ctrl_t *ctrl_p = ft2004_spi_get_ctrl();
FSpi_DevId_t dev_id;
u32 ret = ERR_SPI_OK;
//RT_ASSERT(cfg != RT_NULL);
RT_ASSERT(ctrl_p != RT_NULL);
dev_id = ctrl_p->DevId;
/* get spi flash default config */
ctrl_p->Config = *(ft2004_lookup_conf(dev_id));
/* change config according to inputs, cfg could be RT_NULL */
/* reset ctrl block */
ctrl_p->IsReady = FALSE;
/* set spi pin mux */
Ft_setSpiMux(ctrl_p->CtrlId);
/* init spi ctrl */
ret = FSpi_Init(ctrl_p);
if (ERR_SPI_OK == ret)
{
return RT_EOK;
}
else
{
return -RT_ERROR;
}
}
static rt_uint32_t spi_xfer(struct rt_spi_device *device, struct rt_spi_message *message)
{
rt_size_t message_length, loop;
rt_uint8_t *recv_buf;
const rt_uint8_t *send_buf;
u32 tx_rx_result = ERR_SPI_OK;
spi_cs_handler_t cs_handler = ft2004_spi_get_class()->spi_cs_handler;
RT_ASSERT(device != RT_NULL);
RT_ASSERT(device->bus != RT_NULL);
RT_ASSERT(device->bus->parent.user_data != RT_NULL);
RT_ASSERT(message != RT_NULL);
if (message->cs_take && cs_handler)
{
cs_handler(TRUE);
}
message_length = message->length;
recv_buf = message->recv_buf;
send_buf = message->send_buf;
/* handle msg */
for (loop = 0; loop < message_length; loop++)
{
/* start data exchange */
if ((message->recv_buf) && (message->send_buf))
{
/* need tx and rx */
tx_rx_result |= ft2004_spi_transcation(*send_buf, recv_buf);
send_buf++;
recv_buf++;
}
else if (message->send_buf)
{
/* tx only */
tx_rx_result |= ft2004_spi_transcation(*send_buf, RT_NULL);
send_buf++;
}
else
{
/* rx only */
tx_rx_result |= ft2004_spi_transcation(SPI_DUMMY_TX_DATA, recv_buf);
recv_buf++;
}
}
if (ERR_SPI_OK != tx_rx_result)
{
LOG_E("spi transfer error : 0x%x", tx_rx_result);
message->length = 0;
}
else
{
}
if (message->cs_release && cs_handler)
{
cs_handler(FALSE);
}
return message->length;
}
static rt_err_t spi_configure(struct rt_spi_device *device,
struct rt_spi_configuration *configuration)
{
RT_ASSERT(device != RT_NULL);
RT_ASSERT(configuration != RT_NULL);
return ft2004_spi_init(configuration);
}
static const struct rt_spi_ops ft2004_spi_ops =
{
.configure = spi_configure,
.xfer = spi_xfer,
};
/**
* Attach the spi device to SPI bus, this function must be used after initialization.
*/
rt_err_t rt_hw_spi_device_attach(const char *bus_name, const char *device_name, uint16_t cs_gpio_pin)
{
rt_err_t result;
struct rt_spi_device *spi_device;
ft2004_spi_class *spi_class = ft2004_spi_get_class();
RT_ASSERT(spi_class != RT_NULL);
spi_device = (struct rt_spi_device *)rt_malloc(sizeof(struct rt_spi_device));
RT_ASSERT(spi_device != RT_NULL);
result = rt_spi_bus_attach_device(spi_device, device_name, bus_name, RT_NULL);
LOG_I("attach result 0x%x", result);
if (result != RT_EOK)
{
if (spi_device)
{
rt_free(spi_device);
}
}
return result;
}
static int rt_hw_spi_bus_init(void)
{
rt_err_t result;
ft2004_spi_class *spi_class = ft2004_spi_get_class();
LOG_I("init spi ctrl");
spi_class->spi_bus.parent.user_data = &spi_class->spi_bus;
result = rt_spi_bus_register(&spi_class->spi_bus, SPI_BUS_NAME, &ft2004_spi_ops);
return result;
}
int rt_hw_spi_init(void)
{
return rt_hw_spi_bus_init();
}
INIT_BOARD_EXPORT(rt_hw_spi_init);
static void rthw_spi_delay(u32 delayCnt)
{
Ft_GenericTimer_UsDelay(delayCnt);
}
/************spi flash operatiosn implemented for sample test****************/
/* definition of s25fs maunfactor id */
typedef struct
{
u8 Mid;
u8 MemoryType;
u8 Density;
u8 RemainBytes;
u8 PhySectArch;
u8 FamilyID;
} ft2004_manuid_t;
/* definition of cmd for s25fs */
#define S25FS_ENABLE_WR 0x06
#define S25FS_DISABLE_WR 0x04
#define S25FS_READ_ID 0x9F
#define S25FS_READ_4BYTE_ADD 0x13
#define S25FS_ERASE_4BYTE_ADD 0x21
#define S25FS_READ_STATUS_1 0x05
#define S25FS_READ_FLASH_PARAM 0x5A
static void ft2004_dump_manuid(const ft2004_manuid_t *pId)
{
rt_kprintf("0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x\r\n",
pId->Mid, pId->MemoryType, pId->Density, pId->RemainBytes,
pId->PhySectArch, pId->FamilyID);
}
static u32 ft2004_read_in_4byte_addr(const u32 ReadAddr, const u32 BytesToRead, u8 *pBuf)
{
u32 ret = ERR_SPI_OK;
u32 loop;
RT_ASSERT(RT_NULL != pBuf);
ft2004_spi_cs(TRUE);
ret |= ft2004_spi_transcation(S25FS_READ_4BYTE_ADD, RT_NULL);
/* only 4-bytes address, MSB first */
ret |= ft2004_spi_transcation((u8)(ReadAddr >> 24), RT_NULL);
ret |= ft2004_spi_transcation((u8)(ReadAddr >> 16), RT_NULL);
ret |= ft2004_spi_transcation((u8)(ReadAddr >> 8), RT_NULL);
ret |= ft2004_spi_transcation((u8)ReadAddr, RT_NULL);
/* read out data */
for (loop = 0; loop < BytesToRead; loop++)
{
ret |= ft2004_spi_transcation(SPI_DUMMY_TX_DATA, pBuf + loop);
if (ERR_SPI_OK != ret)
{
break;
}
}
ft2004_spi_cs(FALSE);
return ret;
}
u32 ft2004_spi_enable_wr(const bool_t enable)
{
u32 ret = ERR_SPI_OK;
ft2004_spi_cs(TRUE);
if (enable)
{
ret |= ft2004_spi_transcation(S25FS_ENABLE_WR, RT_NULL);
}
else
{
ret |= ft2004_spi_transcation(S25FS_DISABLE_WR, RT_NULL);
}
ft2004_spi_cs(FALSE);
return ret;
}
u32 ft2004_erase_sector_in_4byte_addr(const u32 sector_addr)
{
u32 Ret = ERR_SPI_OK;
ft2004_spi_enable_wr(TRUE);
LOG_I("erase sector 0x%x", Ret);
if (ERR_SPI_OK != Ret)
{
return Ret;
}
ft2004_spi_cs(TRUE);
Ret |= ft2004_spi_transcation(S25FS_ERASE_4BYTE_ADD, RT_NULL);
Ret |= ft2004_spi_transcation((u8)(sector_addr >> 24), RT_NULL);
Ret |= ft2004_spi_transcation((u8)(sector_addr >> 16), RT_NULL);
Ret |= ft2004_spi_transcation((u8)(sector_addr >> 8), RT_NULL);
Ret |= ft2004_spi_transcation((u8)(sector_addr), RT_NULL);
ft2004_spi_cs(FALSE);
return Ret;
}
u32 ft2004_spi_read_params(const u32 Addr)
{
u32 Ret = ERR_SPI_OK;
u8 dat[8] = {0};
u32 loop;
ft2004_spi_cs(TRUE);
Ret |= ft2004_spi_transcation(S25FS_READ_FLASH_PARAM, RT_NULL);
Ret |= ft2004_spi_transcation((u8)(Addr >> 16), RT_NULL);
Ret |= ft2004_spi_transcation((u8)(Addr >> 8), RT_NULL);
Ret |= ft2004_spi_transcation((u8)(Addr), RT_NULL);
for (loop = 0; loop < 8; loop++)
{
Ret |= ft2004_spi_transcation(SPI_DUMMY_TX_DATA, dat + loop);
rt_kprintf("%d: 0x%x", loop, *(dat + loop));
}
ft2004_spi_cs(FALSE);
return Ret;
}
static u32 ft2004_spi_readid_for_test(ft2004_manuid_t *pId)
{
FSpi_Ctrl_t *ctrl_p = ft2004_spi_get_ctrl();
u32 ret = ERR_SPI_OK;
if (!ctrl_p->IsReady)
{
return ERR_SPI_NOT_READY;
}
RT_ASSERT(RT_NULL != pId);
ft2004_spi_cs(TRUE);
/* shifting the command code “90H” followed by a 24-bit address */
ret |= ft2004_spi_transcation(S25FS_READ_ID, RT_NULL);
/* Manufacturer ID and the Device ID are shifted out */
ret |= ft2004_spi_transcation(SPI_DUMMY_TX_DATA, &pId->Mid);
ret |= ft2004_spi_transcation(SPI_DUMMY_TX_DATA, &pId->MemoryType);
ret |= ft2004_spi_transcation(SPI_DUMMY_TX_DATA, &pId->Density);
ret |= ft2004_spi_transcation(SPI_DUMMY_TX_DATA, &pId->RemainBytes);
ret |= ft2004_spi_transcation(SPI_DUMMY_TX_DATA, &pId->PhySectArch);
ret |= ft2004_spi_transcation(SPI_DUMMY_TX_DATA, &pId->FamilyID);
ft2004_spi_cs(FALSE);
if (ERR_SPI_OK == ret)
{
ft2004_dump_manuid(pId);
}
return ret;
}
static void spi_9f_s25fs_sample(int argc, char *argv[])
{
ft2004_manuid_t dev_id;
u32 ret = ERR_SPI_OK;
u32 delay = SPI_TIMEOUT * 10;
rt_kprintf("test s25fs spi flash\r\n");
ret |= ft2004_spi_init(RT_NULL);
ret |= ft2004_spi_readid_for_test(&dev_id);
rt_kprintf("result is: 0x%x \r\n", ret);
while (--delay)
{
rthw_spi_delay(10);
}
}
MSH_CMD_EXPORT(spi_9f_s25fs_sample, "spi s25fs cmd 9fH sample");
static u8 read_buf[256];
static void spi_5a_s25fs_sample(int argc, char *argv[])
{
u32 ret = ERR_SPI_OK;
u32 delay = SPI_TIMEOUT * 10;
u32 read_addr = 0x0000;
rt_kprintf("test s25fs spi flash\r\n");
ret |= ft2004_spi_init(RT_NULL);
ret |= ft2004_spi_read_params(read_addr);
ret |= ft2004_read_in_4byte_addr(read_addr, 256, read_buf);
rt_kprintf("result is: 0x%x \r\n", ret);
while (--delay)
{
rthw_spi_delay(10);
}
}
MSH_CMD_EXPORT(spi_5a_s25fs_sample, "spi s25fs cmd 5aH sample");
#endif

View File

@ -0,0 +1,29 @@
/*
 * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
 *
 * SPDX-License-Identifier: Apache-2.0.
 *
* @Date: 2021-04-25 14:01:39
* @LastEditTime: 2021-04-29 09:40:13
* @Description:  This files is for
*
* @Modify History:
* Ver   Who        Date         Changes
* ----- ------     --------    --------------------------------------
*/
#ifndef FT_DRIVERS_RTT_SPI_H
#define FT_DRIVERS_RTT_SPI_H
#include <rtthread.h>
#define SPI_BUS_NAME "spi0"
#define SPI_DEV_NAME "S25FS256"
rt_err_t rt_hw_spi_device_attach(const char *bus_name, const char *device_name, uint16_t cs_gpio_pin);
#ifdef __cplusplus
extern "C"
{
#endif
#endif

View File

@ -0,0 +1,43 @@
/*
 * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
 *
 * SPDX-License-Identifier: Apache-2.0.
 *
* @Date: 2021-04-25 14:01:16
* @LastEditTime: 2021-04-30 14:43:12
* @Description:  This files is for
*
* @Modify History:
* Ver   Who        Date         Changes
* ----- ------     --------    --------------------------------------
*/
#include <board.h>
#include <drv_spi.h>
#include <rtdevice.h>
#include <rthw.h>
#include <finsh.h>
#include "ft_spi.h"
#ifdef BSP_USE_SPI
#include "spi_flash.h"
#include "spi_flash_sfud.h"
static int rt_hw_spi_flash_init(void)
{
uint16_t cs_pin = 5;
rt_hw_spi_device_attach(SPI_BUS_NAME, SPI_DEV_NAME, cs_pin);
rt_kprintf("attach spi flash\r\n");
/* lookup flah */
if (RT_NULL == rt_sfud_flash_probe("S25FS256S", SPI_DEV_NAME))
{
rt_kprintf("attach spi flash failed\r\n");
return -RT_ERROR;
}
return RT_EOK;
}
INIT_COMPONENT_EXPORT(rt_hw_spi_flash_init);
#endif

View File

@ -0,0 +1,192 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2021-03-04 Carl the first version
*/
#include "board.h"
#include "drv_usart.h"
#include "interrupt.h"
#include "serial.h"
#include "rtconfig.h"
#ifdef RT_USING_SERIAL
extern u32 FUart_GetInterruptMask(Ft_Uart *uart_ptr);
static void Ft_Os_Uart_Callback(void *Args, u32 Event, u32 EventData);
static void rt_hw_uart_isr(int irqno, void *param)
{
Ft_Uart *uart_ptr = (Ft_Uart *)param;
FUart_InterruptHandler(uart_ptr);
}
static rt_err_t uart_configure(struct rt_serial_device *serial, struct serial_configure *cfg)
{
struct drv_usart *uart = RT_NULL;
Ft_Uart *uart_ptr = RT_NULL;
u32 RegTemp;
u32 ret;
RT_ASSERT(serial != RT_NULL);
RT_ASSERT(cfg != RT_NULL);
uart = rt_container_of(serial, struct drv_usart, serial);
uart_ptr = uart->handle;
RT_ASSERT(FUart_CfgInitialize(uart_ptr, FUart_LookupConfig(uart_ptr->Config.InstanceId)) == FST_SUCCESS);
FUart_SetHandler(uart_ptr, Ft_Os_Uart_Callback, serial);
rt_hw_interrupt_install(uart_ptr->Config.IsrNum, rt_hw_uart_isr, uart_ptr, "uart");
rt_hw_interrupt_umask(uart_ptr->Config.IsrNum);
//<! 设置波特率
ret = FUart_SetBaudRate(uart_ptr, cfg->baud_rate);
RT_ASSERT(ret == FST_SUCCESS);
//<! 打开接收中断
RegTemp = FUart_GetInterruptMask(uart_ptr);
RegTemp |= UARTMIS_RTMIS;
FUart_SetInterruptMask(uart_ptr, RegTemp);
FUart_SetOptions(uart_ptr, FUART_OPTION_UARTEN | FUART_OPTION_RXEN | FUART_OPTION_TXEN | FUART_OPTION_FIFOEN);
return RT_EOK;
}
static rt_err_t uart_control(struct rt_serial_device *serial, int cmd, void *arg)
{
struct drv_usart *uart = RT_NULL;
Ft_Uart *uart_ptr = RT_NULL;
RT_ASSERT(serial != RT_NULL);
uart = rt_container_of(serial, struct drv_usart, serial);
uart_ptr = uart->handle;
switch (cmd)
{
case RT_DEVICE_CTRL_CLR_INT:
/* disable rx irq */
rt_hw_interrupt_mask(uart_ptr->Config.IsrNum);
break;
case RT_DEVICE_CTRL_SET_INT:
/* enable rx irq */
rt_hw_interrupt_umask(uart_ptr->Config.IsrNum);
break;
}
return RT_EOK;
}
static void Ft_Os_Uart_Callback(void *Args, u32 Event, u32 EventData)
{
struct rt_serial_device *serial = (struct rt_serial_device *)Args;
if (FUART_EVENT_RECV_DATA == Event || FUART_EVENT_RECV_TOUT == Event)
{
rt_hw_serial_isr(serial, RT_SERIAL_EVENT_RX_IND);
}
else if (FUART_EVENT_RECV_ERROR == Event)
{
}
else if (FUART_EVENT_SENT_DATA == Event)
{
}
else if (FUART_EVENT_PARE_FRAME_BRKE == Event)
{
}
else if (FUART_EVENT_RECV_ORERR == Event)
{
}
if (FUART_EVENT_SENT_DATA == Event)
{
}
else
{
}
}
static int uart_putc(struct rt_serial_device *serial, char c)
{
struct drv_usart *uart = RT_NULL;
Ft_Uart *uart_ptr = RT_NULL;
RT_ASSERT(serial != RT_NULL);
uart = rt_container_of(serial, struct drv_usart, serial);
uart_ptr = uart->handle;
FUart_SendByte(uart_ptr->Config.BaseAddress, c);
return 1;
}
static int uart_getc(struct rt_serial_device *serial)
{
int ch;
struct drv_usart *uart = RT_NULL;
Ft_Uart *uart_ptr = RT_NULL;
RT_ASSERT(serial != RT_NULL);
uart = rt_container_of(serial, struct drv_usart, serial);
uart_ptr = uart->handle;
ch = FUart_GetChar(uart_ptr->Config.BaseAddress);
if (ch == 0xff)
ch = -1;
return ch;
}
static const struct rt_uart_ops _uart_ops =
{
uart_configure,
uart_control,
uart_putc,
uart_getc,
};
#ifdef RT_USING_UART0
static Ft_Uart Ft_Uart0;
static struct drv_usart _RtUart0;
#endif
#ifdef RT_USING_UART1
static Ft_Uart Ft_Uart1;
static struct drv_usart _RtUart1;
#endif
int rt_hw_uart_init(void)
{
struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT;
#ifdef RT_USING_UART0
config.bufsz = RT_SERIAL_RB_BUFSZ;
_RtUart0.serial.ops = &_uart_ops;
_RtUart0.serial.config = config;
Ft_Uart0.Config.InstanceId = FT_UART0_ID;
_RtUart0.Handle = &Ft_Uart0;
rt_hw_serial_register(&_RtUart0.serial, "uart0",
RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX,
&_RtUart0);
#endif
#ifdef RT_USING_UART1
config.bufsz = RT_SERIAL_RB_BUFSZ;
_RtUart1.serial.ops = &_uart_ops;
_RtUart1.serial.config = config;
Ft_Uart1.Config.InstanceId = FT_UART1_ID;
_RtUart1.handle = &Ft_Uart1;
rt_hw_serial_register(&_RtUart1.serial, "uart1",
RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX,
&_RtUart1);
#endif
return 0;
}
INIT_BOARD_EXPORT(rt_hw_uart_init);
#endif /* RT_USING_SERIAL */

View File

@ -0,0 +1,25 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2021-03-04 Carl the first version
*/
#ifndef __DRV_USART_H__
#define __DRV_USART_H__
#include <rtthread.h>
#include "rtdevice.h"
#include "ft_uart.h"
struct drv_usart
{
Ft_Uart *handle;
struct rt_serial_device serial;
};
#endif // !

View File

@ -0,0 +1,88 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2021-04-29 Carl the first version
*
*/
#include <rtthread.h>
#include "ft2004.h"
#include "gicv3.h"
rt_uint64_t get_main_cpu_affval(void)
{
return 0;
}
rt_uint32_t arm_gic_cpumask_to_affval(rt_uint32_t *cpu_mask, rt_uint32_t *cluster_id, rt_uint32_t *target_list)
{
if (*cpu_mask == 0)
{
return 0;
}
*target_list = 0;
*cluster_id = 0;
if (*cpu_mask & 0x3)
{
if ((*cpu_mask & 0x3) == 0x3)
{
*target_list = 3;
}
else if ((*cpu_mask & 0x1))
{
*target_list = 1;
}
else
{
*target_list = 2;
}
*cpu_mask &= ~0x3;
}
else if (*cpu_mask & 0xc)
{
*cluster_id = 0x100;
if ((*cpu_mask & 0xc) == 0xc)
{
*target_list = 3;
}
else if ((*cpu_mask & 0x4))
{
*target_list = 1;
}
else
{
*target_list = 2;
}
*cpu_mask &= ~0xc;
}
else
{
*cpu_mask = 0;
return 0;
}
return 1;
}
#ifdef RT_USING_SMP
void send_core_isg(void)
{
for (size_t i = 0; i <= 0xf; i++)
{
/* code */
rt_kprintf("i %x \r\n", i);
arm_gic_send_affinity_sgi(0, 0, i, 0);
rt_thread_mdelay(100);
}
}
MSH_CMD_EXPORT(send_core_isg, send_core_isg);
#endif

View File

@ -0,0 +1,25 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2021-04-29 Carl the first version
*
*/
#ifndef __FT2004_H__
#define __FT2004_H__
#include <rthw.h>
#include <rtthread.h>
#define ARM_GIC_NR_IRQS 160
#define ARM_GIC_MAX_NR 1
#define MAX_HANDLERS 160
#define GIC_IRQ_START 0
rt_uint64_t get_main_cpu_affval(void);
#endif // !

View File

@ -0,0 +1,44 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2021-04-29 Carl the first version
*
*/
#include "rtconfig.h"
.globl rt_hw_cpu_id
rt_hw_cpu_id:
mrc p15, 0, r0, c0, c0, 5
ubfx r0, r0, #0, #12
cmp r0, #0
beq core0
cmp r0, #1
beq core1
cmp r0, #256
beq core2
mov r1 ,#257
cmp r0, r1
beq core3
b default
core0:
mov r0, #0
b return
core1:
mov r0, #1
b return
core2:
mov r0, #2
b return
core3:
mov r0, #3
b return
default:
and r0, r0, #15
return:
bx lr

View File

@ -0,0 +1,86 @@
/*
* @ : Copyright (c) 2020 Phytium Information Technology, Inc.
*
* SPDX-License-Identifier: Apache-2.0.
*
* @Date: 2021-05-26 10:09:45
* @LastEditTime: 2021-05-26 10:31:44
* @Description:  This files is for
*
* @Modify History:
*  Ver   Who        Date         Changes
* ----- ------     --------    --------------------------------------
*/
#include <rtthread.h>
#include "board.h"
#include <gicv3.h>
#ifdef RT_USING_SMP
#include <interrupt.h>
#include "ft_psci.h"
#include "ft_generic_timer.h"
extern int rt_hw_timer_init(void);
extern void secondary_cpu_start(void);
void rt_hw_secondary_cpu_up(void)
{
rt_uint32_t i;
rt_uint32_t cpu_mask = 0;
rt_kprintf("rt_hw_secondary_cpu_up is processing \r\n");
for (i = 1; i < RT_CPUS_NR; i++)
{
if (i == 1)
{
/* code */
FPsci_CpuOn(1 << i, (rt_uint32_t)secondary_cpu_start);
cpu_mask = 2;
}
else if (i == 2)
{
FPsci_CpuOn(1 << i, (rt_uint32_t)secondary_cpu_start);
cpu_mask = 4;
}
else if (i == 3)
{
FPsci_CpuOn(1 << i, (rt_uint32_t)secondary_cpu_start);
cpu_mask = 8;
}
else
{
continue;
}
__asm__ volatile("dsb" ::
: "memory");
rt_hw_ipi_send(RT_SCHEDULE_IPI, cpu_mask);
Ft_GenericTimer_UsDelay(1000000);
}
}
void secondary_cpu_c_start(void)
{
rt_hw_vector_init();
rt_hw_spin_lock(&_cpus_lock);
arm_gic_cpu_init(0);
arm_gic_redist_init(0);
rt_hw_timer_init();
rt_hw_interrupt_set_priority(RT_SCHEDULE_IPI, 16);
rt_hw_interrupt_umask(RT_SCHEDULE_IPI);
rt_system_scheduler_start();
}
void rt_hw_secondary_cpu_idle_exec(void)
{
asm volatile("wfe" ::
: "memory", "cc");
}
#endif

View File

@ -0,0 +1,20 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2021-04-29 Carl the first version
*
*/
#ifndef __UART_H__
#define __UART_H__
#include <board.h>
int rt_hw_uart_init(void);
#endif

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

110
bsp/ft2004/ft_aarch32.lds Normal file
View File

@ -0,0 +1,110 @@
OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
OUTPUT_ARCH(arm)
SECTIONS
{
. = 0x80100000;
__text_start = .;
.text :
{
*(.vectors)
*(.text)
*(.text.*)
/* 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 = .;
__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(16 * 1024);
.l1_page_table :
{
__l1_page_table_start = .;
. += 16K;
}
. = ALIGN(8);
__data_start = .;
.data :
{
*(.data)
*(.data.*)
}
__data_end = .;
. = ALIGN(8);
__bss_start = .;
.bss :
{
*(.bss)
*(.bss.*)
*(COMMON)
. = ALIGN(4);
}
. = ALIGN(4);
__bss_end = .;
.heap :
{
. = ALIGN(8);
__end__ = .;
PROVIDE(end = .);
__HeapBase = .;
. += 0x400;
__HeapLimit = .;
__heap_limit = .; /* Add for _sbrk */
}
/* Stabs debugging sections. */
.stab 0 : { *(.stab) }
.stabstr 0 : { *(.stabstr) }
.stab.excl 0 : { *(.stab.excl) }
.stab.exclstr 0 : { *(.stab.exclstr) }
.stab.index 0 : { *(.stab.index) }
.stab.indexstr 0 : { *(.stab.indexstr) }
.comment 0 : { *(.comment) }
_end = .;
}

4
bsp/ft2004/libraries/.gitignore vendored Normal file
View File

@ -0,0 +1,4 @@
*.o
*.elf
*.bin
*.map

View File

@ -0,0 +1,146 @@
menu "Hardware Drivers Config"
menu "On-chip Peripheral Drivers"
menuconfig BSP_USING_UART
bool "Enable UART"
default y
select RT_USING_SERIAL
if BSP_USING_UART
config RT_USING_UART1
bool "Enable UART1"
default y
config RT_USING_UART0
bool "Enable UART0"
default n
endif
menuconfig BSP_USING_SDC
bool "Enable sd controller"
select RT_USING_SDIO
select RT_USING_DFS
select RT_USING_DFS_ELMFAT
default n
if BSP_USING_SDC
config BSP_SDC_DEBUG_PRINT
bool "Enable sd controller debug print"
default n
config BSP_SDC_USE_IRQ
bool "Use interrupt to handle when cmd complete, dma complete"
default n
if BSP_SDC_USE_IRQ
config BSP_SDC_IRQ_CARD_REMOVE
bool "Use interrupt to determine if the card is pulled out"
default n
endif
endif
menuconfig BSP_USING_GMAC
bool "Enable gmac"
default n
select RT_USING_NETDEV
if BSP_USING_GMAC
config BSP_USING_GMAC0
bool "Enable GMAC0"
default y
config BSP_USING_GMAC1
bool "Enable GMAC1"
default n
config RT_LWIP_ETH_PAD_SIZE
int "set lwip ETH_PAD_SIZE"
range 2 256
default 2
config RAW_DATA_PRINT
bool "Enable mac raw data print"
default n
if RAW_DATA_PRINT
config ETH_RX_DUMP
bool "Enable gmac receive raw data print "
default n
config ETH_TX_DUMP
bool "Enable gmac send raw data print "
default n
endif
endif
# menuconfig BSP_USE_QSPI
# bool "Enable Qspi"
# select RT_USING_SFUD
# select RT_SFUD_USING_QSPI
# default n
# if BSP_USE_QSPI
# config BSP_QSPI_DEBUG
# bool "Enable qspi debug print"
# default n
# endif
menuconfig BSP_USE_SPI
bool "Enable Spi"
select RT_USING_SFUD
select RT_SFUD_USING_SPI
select RT_SFUD_USING_SFDP
select RT_SFUD_USING_FLASH_INFO_TABLE
select BSP_USE_GPIO
default n
if BSP_USE_SPI
config BSP_SPI_DEBUG
bool "Enable spi debug print"
default n
endif
menuconfig BSP_USE_GPIO
bool "Enable Gpio"
default n
if BSP_USE_GPIO
config BSP_GPIO_DEBUG
bool "Enable gpio debug print"
default n
endif
menuconfig BSP_USE_CAN
bool "Enable Can"
select RT_USING_CAN
default n
if BSP_USE_CAN
config BSP_USING_CAN0
bool "Enable can0"
default n
config BSP_USING_CAN1
bool "Enable can1"
default n
if BSP_USING_CAN0
config BSP_USING_CAN0_DEBUG
bool "Enable can0 work in loop back"
default n
endif
endif
endmenu
menu "Board extended module Drivers"
endmenu
endmenu

View File

@ -0,0 +1,202 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View File

@ -0,0 +1,129 @@
'''
 : Copyright (c) 2020 Phytium Information Technology, Inc. 
 
SPDX-License-Identifier: Apache-2.0.
Date: 2021-05-24 14:30:13
LastEditTime: 2021-05-26 14:58:34
Description:  This files is for 
Modify History:
 Ver   Who        Date         Changes
----- ------     --------    --------------------------------------
'''
from building import *
import rtconfig
Import('RTT_ROOT')
# get current directory
cwd = GetCurrentDir()
# The set of source files associated with this SConscript file.
src = Split("""
bsp/standlone/ft_assert.c
bsp/standlone/ft_generic_timer.c
bsp/standlone/ft_printf.c
bsp/standlone/ft_trace.c
bsp/standlone/ft_mux.c
bsp/standlone/inbyte.c
bsp/standlone/outbyte.c
bsp/standlone/ft_cache.c
bsp/standlone/ft_cpu.c
bsp/standlone/ft_smc.S
bsp/standlone/ft_psci.c
bsp/standlone/ft_debug.c
""")
if GetDepend(['RT_USING_SERIAL']):
src += ['bsp/ft_uart/ft_uart_g.c']
src += ['bsp/ft_uart/ft_uart_hw.c']
src += ['bsp/ft_uart/ft_uart_intr.c']
src += ['bsp/ft_uart/ft_uart_options.c']
src += ['bsp/ft_uart/ft_uart_selftest.c']
src += ['bsp/ft_uart/ft_uart_sinit.c']
src += ['bsp/ft_uart/ft_uart.c']
if GetDepend(['RT_USING_I2C']):
None
if GetDepend(['RT_USING_USB_HOST']) or GetDepend(['RT_USING_USB_DEVICE']):
None
if GetDepend(['BSP_USE_CAN']):
src += ['bsp/ft_can/ft_can_g.c']
src += ['bsp/ft_can/ft_can_hw.c']
src += ['bsp/ft_can/ft_can_intr.c']
src += ['bsp/ft_can/ft_can_sinit.c']
src += ['bsp/ft_can/ft_can.c']
src += ['bsp/ft_can/ft_can_calc.c']
None
if GetDepend(['RT_USING_HWTIMER']) or GetDepend(['RT_USING_PWM']):
None
if GetDepend(['RT_USING_ADC']):
None
if GetDepend(['RT_USING_RTC']):
None
if GetDepend(['RT_USING_WDT']):
None
if GetDepend(['RT_USING_AUDIO']):
None
if GetDepend(['BSP_USING_ON_CHIP_FLASH']):
None
if GetDepend(['BSP_USING_GMAC']):
src += ['bsp/ft_gmac/ft_gmac_desc.c']
src += ['bsp/ft_gmac/ft_gmac_g.c']
src += ['bsp/ft_gmac/ft_gmac_hw.c']
src += ['bsp/ft_gmac/ft_gmac_intr.c']
src += ['bsp/ft_gmac/ft_gmac_sinit.c']
src += ['bsp/ft_gmac/ft_gmac.c']
if GetDepend(['BSP_USING_SDC']):
src += ['bsp/ft_sd/ft_sdctrl_option.c']
src += ['bsp/ft_sd/ft_sdctrl_sinit.c']
src += ['bsp/ft_sd/ft_sdctrl_intr.c']
src += ['bsp/ft_sd/ft_sdctrl_g.c']
src += ['bsp/ft_sd/ft_sdctrl_hw.c']
src += ['bsp/ft_sd/ft_sdctrl.c']
if GetDepend(['BSP_USE_QSPI']):
src += ['bsp/ft_qspi/qspi_g.c']
src += ['bsp/ft_qspi/qspi_hw.c']
src += ['bsp/ft_qspi/ft_qspi.c']
src += ['bsp/ft_qspi/qspi_sinit.c']
if GetDepend(['BSP_USE_SPI']):
src += ['bsp/ft_spi/ft_spi.c']
src += ['bsp/ft_spi/ft_spi_irq.c']
if GetDepend(['BSP_USE_GPIO']):
src += ['bsp/ft_gpio/ft_gpio.c']
path = [cwd + '/bsp/standlone/',
cwd + '/bsp/ft_gicv3',
cwd + '/bsp/ft_gmac',
cwd + '/bsp/ft_uart',
cwd + '/bsp/ft_sd',
cwd + '/bsp/ft_qspi',
cwd + '/bsp/ft_can',
cwd + '/bsp/ft_spi',
cwd + '/bsp/ft_gpio',
cwd + '/bsp/include',
cwd + '/include',
cwd + '/cpu', ]
CPPDEFINES = ['USE_FT_DRIVER']
group = DefineGroup('FT_DRIVER', src, depend=[
''], CPPPATH=path, CPPDEFINES=CPPDEFINES)
Return('group')

View File

@ -0,0 +1,299 @@
/*
 * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
 *
 * SPDX-License-Identifier: Apache-2.0.
*
* @Date: 2021-04-29 10:21:53
* @LastEditTime: 2021-05-25 16:41:38
* @Description:  Description of file
* @Modify History:
* * * Ver   Who        Date         Changes
* * ----- ------     --------    --------------------------------------
*/
#include "ft_can.h"
#include "ft_can_hw.h"
#include "ft_assert.h"
#include "ft_debug.h"
#include "string.h"
#define FT_CAN_DEBUG_TAG "FT_CAN"
#define FT_CAN_DEBUG_I(format, ...) FT_DEBUG_PRINT_I(FT_CAN_DEBUG_TAG, format, ##__VA_ARGS__)
#define FT_CAN_DEBUG_E(format, ...) FT_DEBUG_PRINT_E(FT_CAN_DEBUG_TAG, format, ##__VA_ARGS__)
#define FT_CAN_DEBUG_W(format, ...) FT_DEBUG_PRINT_W(FT_CAN_DEBUG_TAG, format, ##__VA_ARGS__)
ft_error_t
FCan_CfgInitialize(FCan_t *Can_p, FCan_Config_t *Config_p)
{
Ft_assertNonvoid(Can_p != NULL);
Ft_assertNonvoid(Config_p != NULL);
Can_p->Config = *Config_p;
Can_p->IsReady = FT_COMPONENT_IS_READLY;
FCan_Reset(Can_p);
return FCAN_SUCCESS;
}
void FCan_GetErrorCnt(FCan_t *Can_p, u32 *TxErr, u32 *RxErr)
{
FCan_Config_t *Config_p;
Ft_assertVoid(Can_p != NULL);
Ft_assertVoid(Can_p->IsReady == FT_COMPONENT_IS_READLY);
Config_p = &Can_p->Config;
*RxErr = FCan_ReadReg(Config_p->CanBaseAddress, FCAN_ERR_CNT_OFFSET) & FCAN_ERR_CNT_RFN_MASK;
*TxErr = (FCan_ReadReg(Config_p->CanBaseAddress, FCAN_ERR_CNT_OFFSET) & FCAN_ERR_CNT_TFN_MASK) >> FCAN_ERR_CNT_TFN_SHIFT;
}
u32 FCan_RecvByIrq(FCan_t *Can_p, struct FCan_Frame *Frame_p, u32 FrameNumber)
{
u32 FifoCnt = 0;
FCan_Config_t *Config_p;
u32 CanId;
u32 Dlc;
u32 CanFrameIndex = 0;
u32 RxValue;
Ft_assertZeroNum(Can_p != NULL);
Ft_assertZeroNum(Can_p->IsReady == FT_COMPONENT_IS_READLY);
Config_p = &Can_p->Config;
FifoCnt = FCan_ReadReg(Config_p->CanBaseAddress, FCAN_FIFO_CNT_OFFSET) & 0x3f;
if (0 == FifoCnt)
{
return 0;
}
FrameNumber = (FrameNumber > FifoCnt) ? FifoCnt : FrameNumber;
while (FrameNumber)
{
/* Read a frame from Phytium CAN */
CanId = FCan_ReadReg(Config_p->CanBaseAddress, FCAN_RX_FIFO_OFFSET);
/* if CanId is big-endian ,use swap change to little-endian */
CanId = FT_SWAP32(CanId);
/* Identifier extension */
if (CanId & FCAN_IDR_IDE_MASK)
{
Dlc = FCan_ReadReg(Config_p->CanBaseAddress, FCAN_RX_FIFO_OFFSET);
Dlc = FT_SWAP32(Dlc);
Dlc = ((Dlc & FCAN_IDR_EDLC_MASK) >> FCAN_IDR_EDLC_SHIFT);
Frame_p[CanFrameIndex].CanId = (CanId & FCAN_IDR_ID1_MASK) >> 3;
Frame_p[CanFrameIndex].CanId |= (CanId & FCAN_IDR_ID2_MASK) >> FCAN_IDR_ID2_SHIFT;
Frame_p[CanFrameIndex].CanId |= CAN_EFF_FLAG;
if (CanId & FCAN_IDR_RTR_MASK)
{
Frame_p[CanFrameIndex].CanId |= CAN_RTR_FLAG;
}
}
else
{
Dlc = ((CanId & FCAN_IDR_DLC_MASK) >> FCAN_IDR_SDLC_SHIFT);
/* The received frame is a standard format frame */
Frame_p[CanFrameIndex].CanId = (CanId & FCAN_IDR_ID1_MASK) >> FCAN_IDR_ID1_SHIFT;
if (CanId & FCAN_IDR_SRR_MASK)
{
Frame_p[CanFrameIndex].CanId |= CAN_RTR_FLAG;
}
}
Frame_p[CanFrameIndex].CanDlc = (Dlc > sizeof(Frame_p[CanFrameIndex].data)) ? sizeof(Frame_p[CanFrameIndex].data) : Dlc;
if (!(Frame_p[CanFrameIndex].CanId & CAN_RTR_FLAG))
{
if (Frame_p[CanFrameIndex].CanDlc > 0)
{
RxValue = FCan_ReadReg(Config_p->CanBaseAddress, FCAN_RX_FIFO_OFFSET);
memcpy(Frame_p[CanFrameIndex].data, &RxValue, sizeof(RxValue));
}
if (Frame_p[CanFrameIndex].CanDlc > 4)
{
RxValue = FCan_ReadReg(Config_p->CanBaseAddress, FCAN_RX_FIFO_OFFSET);
memcpy(&Frame_p[CanFrameIndex].data[4], &RxValue, sizeof(RxValue));
}
}
FrameNumber--;
CanFrameIndex++;
}
return (CanFrameIndex + 1);
}
static void FCan_SendFifo(FCan_t *Can_p, struct FCan_Frame *Frame_p)
{
u32 Id, Dlc;
FCan_Config_t *Config_p;
u32 SendBuffer = 0;
Ft_assertVoid(Can_p != NULL);
Ft_assertVoid(Can_p->IsReady == FT_COMPONENT_IS_READLY);
Config_p = &Can_p->Config;
if (Frame_p->CanId & CAN_EFF_FLAG)
{
/* Extended CAN ID format */
Id = ((Frame_p->CanId & CAN_EFF_MASK) << FCAN_IDR_ID2_SHIFT) &
FCAN_IDR_ID2_MASK;
Id |= (((Frame_p->CanId & CAN_EFF_MASK) >>
(CAN_EFF_ID_BITS - CAN_SFF_ID_BITS))
<< FCAN_IDR_ID1_SHIFT) &
FCAN_IDR_ID1_MASK;
Id |= FCAN_IDR_IDE_MASK | FCAN_IDR_SRR_MASK;
if (Frame_p->CanId & CAN_RTR_FLAG)
{
Id |= FCAN_IDR_RTR_MASK;
}
Dlc = Frame_p->CanDlc << FCAN_IDR_EDLC_SHIFT;
FCan_WriteReg(Config_p->CanBaseAddress, FCAN_TX_FIFO_OFFSET, FT_SWAP32(Id));
FCan_WriteReg(Config_p->CanBaseAddress, FCAN_TX_FIFO_OFFSET, FT_SWAP32(Dlc));
}
else
{
/* Standard CAN ID format */
Id = ((Frame_p->CanId & CAN_SFF_MASK) << FCAN_IDR_ID1_SHIFT) &
FCAN_IDR_ID1_MASK;
if (Frame_p->CanId & CAN_RTR_FLAG)
Id |= FCAN_IDR_SRR_MASK;
Dlc = ((Frame_p->CanDlc << FCAN_IDR_SDLC_SHIFT) | FCAN_IDR_PAD_MASK);
Id |= Dlc;
FCan_WriteReg(Config_p->CanBaseAddress, FCAN_TX_FIFO_OFFSET, FT_SWAP32(Id));
}
if (!(Frame_p->CanId & CAN_RTR_FLAG))
{
if (Frame_p->CanDlc > 0)
{
memcpy(&SendBuffer, Frame_p->data, 4);
FCan_WriteReg(Config_p->CanBaseAddress, FCAN_TX_FIFO_OFFSET, SendBuffer);
}
if (Frame_p->CanDlc > 4)
{
memcpy(&SendBuffer, &Frame_p->data[4], 4);
FCan_WriteReg(Config_p->CanBaseAddress, FCAN_TX_FIFO_OFFSET, SendBuffer);
}
}
}
u32 FCan_SendByIrq(FCan_t *Can_p,
struct FCan_Frame *Frame_p,
u32 FrameNumber, void (*UserIrqWait)(void))
{
FCan_Config_t *Config_p;
u32 FrameIndex = 0;
u32 NeedSendOnce;
u32 cnt = 0;
Ft_assertZeroNum(Can_p != NULL);
Ft_assertZeroNum(Can_p->IsReady == FT_COMPONENT_IS_READLY);
Config_p = &Can_p->Config;
if (NULL == Frame_p)
{
FT_CAN_DEBUG_E("Frame_p is NULL , %s: %d", __FILE__, __LINE__);
return 0;
}
if (0 == FrameNumber)
{
FT_CAN_DEBUG_E("FrameNumber is 0 , %s: %d", __FILE__, __LINE__);
return 0;
}
for (; 0 < FrameNumber;)
{
if (FrameNumber > Config_p->TxFifoDeepth)
{
NeedSendOnce = Config_p->TxFifoDeepth;
FrameNumber -= Config_p->TxFifoDeepth;
}
else
{
NeedSendOnce = FrameNumber;
FrameNumber = 0;
}
Ft_printf("shut down tranmission \r\n");
/*shut down tranmission*/
FCan_ClearBit(Config_p->CanBaseAddress, FCAN_CTRL_OFFSET, FCAN_CTRL_XFER_MASK);
FCan_ClearBit(Config_p->CanBaseAddress, FCAN_CTRL_OFFSET, FCAN_CTRL_TXREQ_MASK);
FCan_SetBit(Config_p->CanBaseAddress, FCAN_CTRL_OFFSET, FCAN_CTRL_XFER_MASK);
Ft_printf("NeedSendOnce %d \r\n", NeedSendOnce);
for (cnt = 0; cnt < NeedSendOnce; cnt++)
{
FCan_SendFifo(Can_p, &Frame_p[FrameIndex]);
FrameIndex++;
}
Can_p->TxFifoCnt = NeedSendOnce;
/* triggers tranmission */
FCan_ClearBit(Config_p->CanBaseAddress, FCAN_CTRL_OFFSET, FCAN_CTRL_XFER_MASK);
FCan_SetBit(Config_p->CanBaseAddress, FCAN_CTRL_OFFSET, FCAN_CTRL_TXREQ_MASK);
FCan_SetBit(Config_p->CanBaseAddress, FCAN_CTRL_OFFSET, FCAN_CTRL_TXREQ_MASK | FCAN_CTRL_XFER_MASK);
if (UserIrqWait)
{
UserIrqWait();
}
else
{
while (0 != Can_p->TxFifoCnt)
{
};
}
}
return FrameIndex + 1;
}
ft_error_t FCan_SetTiming(FCan_t *Can_p,
struct FCan_Bittiming *Bittiming_p)
{
u32 Btr = 0;
FCan_Config_t *Config_p;
u32 IsConfigMode;
Ft_assertNonvoid(Can_p != NULL);
Ft_assertNonvoid(Can_p->IsReady == FT_COMPONENT_IS_READLY);
Config_p = &Can_p->Config;
Ft_assertNonvoid(Bittiming_p->brp != 0);
Ft_assertNonvoid(Bittiming_p->prop_seg != 0);
Ft_assertNonvoid(Bittiming_p->phase_seg1 != 0);
Ft_assertNonvoid(Bittiming_p->phase_seg2 != 0);
/* Setting Baud Rate prescalar value in BRPR Register */
Btr = (Bittiming_p->brp - 1) << 16;
Btr |= (Bittiming_p->prop_seg - 1) << 2;
Btr |= (Bittiming_p->phase_seg1 - 1) << 5;
Btr |= (Bittiming_p->phase_seg2 - 1) << 8;
Btr |= (Bittiming_p->sjw - 1);
IsConfigMode = (FCan_ReadReg(Config_p->CanBaseAddress, FCAN_CTRL_OFFSET) & FCAN_CTRL_XFER_MASK);
if (IsConfigMode)
{
FCan_WriteReg(Config_p->CanBaseAddress, FCAN_CTRL_OFFSET, FCAN_CTRL_XFER_MASK);
}
FCan_WriteReg(Config_p->CanBaseAddress, FCAN_DAT_RATE_CTRL_OFFSET, Btr);
FCan_WriteReg(Config_p->CanBaseAddress, FCAN_ARB_RATE_CTRL_OFFSET, Btr);
/*Enable Transfer*/
FCan_SetBit(Config_p->CanBaseAddress, FCAN_CTRL_OFFSET, FCAN_CTRL_XFER_MASK);
return FCAN_SUCCESS;
}
void FCan_Enable(FCan_t *Can_p)
{
FCan_Config_t *Config_p;
Ft_assertVoid(Can_p != NULL);
Ft_assertVoid(Can_p->IsReady == FT_COMPONENT_IS_READLY);
Config_p = &Can_p->Config;
FCan_WriteReg(Config_p->CanBaseAddress, FCAN_CTRL_OFFSET, FCAN_CTRL_XFER_MASK);
}

View File

@ -0,0 +1,142 @@
/*
 * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
 *
 * SPDX-License-Identifier: Apache-2.0.
*
* @Date: 2021-04-27 15:08:44
* @LastEditTime: 2021-04-27 15:08:44
* @Description:  Description of file
* @Modify History:
* * * Ver   Who        Date         Changes
* * ----- ------     --------    --------------------------------------
*/
#ifndef FT_CAN_H
#define FT_CAN_H
#include "ft_types.h"
#include "ft_error_code.h"
#define FCAN_SUCCESS FST_SUCCESS /* SUCCESS */
#define FCAN_FAILURE FT_MAKE_ERRCODE(errCan, errBspGeneral, FST_FAILURE) /* Normal */
#define FCAN_TIMEOUT FT_MAKE_ERRCODE(errCan, errBspGeneral, FST_TIMEOUT) /* Timeout */
#define FCAN_EILSEQ FT_MAKE_ERRCODE(errCan, errBspGeneral, FST_EILSEQ) /* Illegal byte sequence. */
#define FCAN_INVALID_PARAM FT_MAKE_ERRCODE(errCan, errBspGeneral, FST_INVALID_PARAM) /* Invalid param. */
#define FCAN_HANDLER_SEND 1U /**< Handler type for frame sending interrupt */
#define FCAN_HANDLER_RECV 2U /**< Handler type for frame reception interrupt*/
#define FCAN_HANDLER_ERROR 3U /**< Handler type for error interrupt */
#define FCAN_DATA_LENGTH 8U
/* CAN payload length and DLC definitions according to ISO 11898-1 */
#define CAN_MAX_DLC 8
#define CAN_MAX_DLEN 8
#define CAN_MAX_CTL 3
#define CAN_SFF_ID_BITS 11
#define CAN_EFF_ID_BITS 29
/* special address description flags for the CAN_ID */
#define CAN_EFF_FLAG 0x80000000U /* EFF/SFF is set in the MSB */
#define CAN_RTR_FLAG 0x40000000U /* remote transmission request */
#define CAN_ERR_FLAG 0x20000000U /* error message frame */
/* valid bits in CAN ID for frame formats */
#define CAN_SFF_MASK 0x000007FFU /* standard frame format (SFF) */
#define CAN_EFF_MASK 0x1FFFFFFFU /* extended frame format (EFF) */
#define CAN_ERR_MASK 0x1FFFFFFFU /* omit EFF, RTR, ERR flags */
/* Frame type */
#define STANDARD_FRAME 0 /* standard frame */
#define EXTEND_FRAME 1 /* extended frame */
typedef void (*FCan_irqHandler_t)(void *Args);
struct FCan_Frame
{
u32 CanId;
u8 CanDlc;
u8 data[FCAN_DATA_LENGTH];
};
struct FCan_Bittiming
{
u32 bitrate; /* Bit-rate in bits/second */
u32 sample_point; /* Sample point in one-tenth of a percent */
u32 tq; /* Time quanta (TQ) in nanoseconds */
u32 prop_seg; /* Propagation segment in TQs */
u32 phase_seg1; /* Phase buffer segment 1 in TQs */
u32 phase_seg2; /* Phase buffer segment 2 in TQs */
u32 sjw; /* Synchronisation jump width in TQs */
u32 brp; /* Bit-rate prescaler */
};
typedef struct
{
u32 InstanceId; /* Id of device */
u32 CanBaseAddress; /* Can base Address */
u32 IrqNum;
u32 BaudRate;
u32 TxFifoDeepth; /* The depth of the full frame , */
} FCan_Config_t;
typedef struct
{
FCan_Config_t Config;
u32 IsReady; /* Device is initialized and ready */
volatile u32 TxFifoCnt;
FCan_irqHandler_t SendHandler;
void *SendRef;
FCan_irqHandler_t RecvHandler;
void *RecvRef;
FCan_irqHandler_t ErrorHandler;
void *ErrorRef;
} FCan_t;
FCan_Config_t *FCan_LookupConfig(u32 InstanceId);
/**
* @name: FCan_CfgInitialize
* @msg: This function initializes a Can instance/driver.
* @in param Can_p: Can_p is a pointer to the FCan_t instance.
* @in param Config_p: Config_p points to the FCan_t device configuration structure.
* @return {*}
*/
ft_error_t FCan_CfgInitialize(FCan_t *Can_p, FCan_Config_t *Config_p);
/**
* @name: FCan_SetHandler
* @msg: This routine installs an asynchronous callback function for the given
* @inout param Can_p: Can_p is a pointer to the FCan_t instance.
* @in param HandlerType: specifies which handler is to be attached.
* @in param IrqCallBackFunc: IrqCallBackFunc is the address of the callback function.
* @in param IrqCallBackRef: IrqCallBackRef is a user data item that will be passed to the
* callback function when it is invoked.
* @return {*}
* @param {FCan_t} *Can_p
* @param {u32} HandlerType
* @param {FCan_irqHandler_t} *IrqCallBackFunc
* @param {void} *IrqCallBackRef
*/
ft_error_t FCan_SetHandler(FCan_t *Can_p, u32 HandlerType, FCan_irqHandler_t IrqCallBackFunc, void *IrqCallBackRef);
ft_error_t FCan_SetTiming(FCan_t *Can_p,
struct FCan_Bittiming *Bittiming_p);
void FCan_IntrHandler(void *InstancePtr);
ft_error_t FCan_CalcBittiming(struct FCan_Bittiming *Bt_p);
u32 FCan_SendByIrq(FCan_t *Can_p,
struct FCan_Frame *Frame_p,
u32 FrameNumber, void (*UserIrqWait)(void));
u32 FCan_RecvByIrq(FCan_t *Can_p, struct FCan_Frame *Frame_p, u32 FrameNumber);
void FCan_Enable(FCan_t *Can_p);
#endif // !FT_CAN_H

View File

@ -0,0 +1,269 @@
/*
 * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
 *
 * SPDX-License-Identifier: Apache-2.0.
*
* @Date: 2021-05-06 09:30:51
* @LastEditTime: 2021-05-25 16:41:10
* @Description:  Description of file
* @Modify History:
* * * Ver   Who        Date         Changes
* * ----- ------     --------    --------------------------------------
*/
#include "ft_can.h"
#include "ft_debug.h"
#include "string.h"
#ifndef max
#define max(x, y) (((x) < (y)) ? (y) : (x))
#endif
#ifndef min
#define min(x, y) (((x) < (y)) ? (x) : (y))
#endif
#define FT_CAN_DEBUG_TAG "FT_CAN"
#define FT_CAN_DEBUG_I(format, ...) FT_DEBUG_PRINT_I(FT_CAN_DEBUG_TAG, format, ##__VA_ARGS__)
#define FT_CAN_DEBUG_E(format, ...) FT_DEBUG_PRINT_E(FT_CAN_DEBUG_TAG, format, ##__VA_ARGS__)
#define FT_CAN_DEBUG_W(format, ...) FT_DEBUG_PRINT_W(FT_CAN_DEBUG_TAG, format, ##__VA_ARGS__)
#define CAN_CLK_FREQ 600000000
#define CAN_CALC_SYNC_SEG 1
#define FCAN_TSEG1_MIN 1
#define FCAN_TSEG1_MAX 8
#define FCAN_TSEG2_MIN 1
#define FCAN_TSEG2_MAX 8
#define FCAN_SJW_MAX 4
#define FCAN_BRP_MIN 1
#define FCAN_BRP_MAX 512
#define FCAN_BRP_INC 1
#define FCAN_CALC_SYNC_SEG 1
#define CAN_CALC_MAX_ERROR 50 /* in one-tenth of a percent */
#define BEST_BITRATE_ERROR (2147483647 * 2U + 1)
#define clamp(x, low, high) (min(max(low, x), high))
typedef struct can_bittiming_const
{
char name[16]; /* Name of the CAN controller hardware */
u32 tseg1_min; /* Time segement 1 = prop_seg + phase_seg1 */
u32 tseg1_max;
u32 tseg2_min; /* Time segement 2 = phase_seg2 */
u32 tseg2_max;
u32 sjw_max; /* Synchronisation jump width */
u32 brp_min; /* Bit-rate prescaler */
u32 brp_max;
u32 brp_inc;
} FTCAN_BITTIMING_CONST;
static const struct can_bittiming_const ftcan_bittiming_const = {
.name = "vxbftCan",
.tseg1_min = 1,
.tseg1_max = 8,
.tseg2_min = 1,
.tseg2_max = 8,
.sjw_max = 4,
.brp_min = 1,
.brp_max = 512,
.brp_inc = 1,
};
static int abs(
int i /* integer for which to return absolute value */
)
{
return (i >= 0 ? i : -i);
}
static u32 div64_32(u64 *n, u32 base)
{
u64 rem = *n;
u64 b = base;
u64 res, d = 1;
u32 high = rem >> 32;
/* Reduce the thing a bit first */
res = 0;
if (high >= base)
{
high /= base;
res = (u64)high << 32;
rem -= (u64)(high * base) << 32;
}
while ((u64)b > 0 && b < rem)
{
b = b + b;
d = d + d;
}
do
{
if (rem >= b)
{
rem -= b;
res += d;
}
b >>= 1;
d >>= 1;
} while (d);
*n = res;
return rem;
}
s32 can_update_sample_point(const struct can_bittiming_const *btc,
u32 sample_point_nominal, u32 tseg,
u32 *tseg1_ptr, u32 *tseg2_ptr,
u32 *sample_point_error_ptr)
{
u32 sample_point_error, best_sample_point_error = BEST_BITRATE_ERROR;
u32 sample_point, best_sample_point = 0;
u32 tseg1, tseg2;
s32 i;
for (i = 0; i <= 1; i++)
{
tseg2 = tseg + CAN_CALC_SYNC_SEG - (sample_point_nominal * (tseg + CAN_CALC_SYNC_SEG)) / 1000 - i;
tseg2 = clamp(tseg2, btc->tseg2_min, btc->tseg2_max);
tseg1 = tseg - tseg2;
if (tseg1 > btc->tseg1_max)
{
tseg1 = btc->tseg1_max;
tseg2 = tseg - tseg1;
}
sample_point = 1000 * (tseg + CAN_CALC_SYNC_SEG - tseg2) / (tseg + CAN_CALC_SYNC_SEG);
sample_point_error = abs(sample_point_nominal - sample_point);
if ((sample_point <= sample_point_nominal) && (sample_point_error < best_sample_point_error))
{
best_sample_point = sample_point;
best_sample_point_error = sample_point_error;
*tseg1_ptr = tseg1;
*tseg2_ptr = tseg2;
}
}
if (sample_point_error_ptr)
*sample_point_error_ptr = best_sample_point_error;
return best_sample_point;
}
ft_error_t FCan_CalcBittiming(struct FCan_Bittiming *Bt_p)
{
u32 bitrate; /* current bitrate */
u32 bitrate_error; /* difference between current and nominal value */
u32 best_bitrate_error = BEST_BITRATE_ERROR;
u32 sample_point_error; /* difference between current and nominal value */
u32 best_sample_point_error = BEST_BITRATE_ERROR;
u32 sample_point_nominal; /* nominal sample point */
u32 best_tseg = 0; /* current best value for tseg */
u32 best_brp = 0; /* current best value for brp */
u32 brp, tsegall, tseg, tseg1 = 0, tseg2 = 0;
u64 v64;
const struct can_bittiming_const *btc = &ftcan_bittiming_const;
struct FCan_Bittiming *bt = Bt_p;
if (bt->sample_point)
{
sample_point_nominal = bt->sample_point;
}
else
{
if (bt->bitrate > 800000)
sample_point_nominal = 750;
else if (bt->bitrate > 500000)
sample_point_nominal = 800;
else
sample_point_nominal = 875;
}
for (tseg = (btc->tseg1_max + btc->tseg2_max) * 2 + 1;
tseg >= (btc->tseg1_min + btc->tseg2_min) * 2; tseg--)
{
tsegall = CAN_CALC_SYNC_SEG + tseg / 2;
/* Compute all possible tseg choices (tseg=tseg1+tseg2) */
brp = CAN_CLK_FREQ / (tsegall * bt->bitrate) + tseg % 2;
/* choose brp step which is possible in system */
brp = (brp / btc->brp_inc) * btc->brp_inc;
if ((brp < btc->brp_min) || (brp > btc->brp_max))
continue;
bitrate = CAN_CLK_FREQ / (brp * tsegall);
bitrate_error = abs(bt->bitrate - bitrate);
/* tseg brp biterror */
if (bitrate_error > best_bitrate_error)
continue;
/* reset sample point error if we have a better bitrate */
if (bitrate_error < best_bitrate_error)
best_sample_point_error = BEST_BITRATE_ERROR;
can_update_sample_point(btc, sample_point_nominal, tseg / 2, &tseg1, &tseg2, &sample_point_error);
if (sample_point_error > best_sample_point_error)
continue;
best_sample_point_error = sample_point_error;
best_bitrate_error = bitrate_error;
best_tseg = tseg / 2;
best_brp = brp;
if (bitrate_error == 0 && sample_point_error == 0)
break;
}
if (best_bitrate_error)
{
/* Error in one-tenth of a percent */
v64 = (u64)best_bitrate_error * 1000;
div64_32(&v64, bt->bitrate);
bitrate_error = (u32)v64;
if (bitrate_error > CAN_CALC_MAX_ERROR)
{
FT_CAN_DEBUG_E("bitrate error");
}
return FCAN_FAILURE;
FT_CAN_DEBUG_E("bitrate error 2");
}
/* real sample point */
bt->sample_point = can_update_sample_point(btc, sample_point_nominal, best_tseg,
&tseg1, &tseg2, NULL);
v64 = (u64)best_brp * 1000 * 1000 * 1000;
div64_32(&v64, CAN_CLK_FREQ);
bt->tq = (u64)v64;
bt->prop_seg = tseg1 / 2;
bt->phase_seg1 = tseg1 - bt->prop_seg;
bt->phase_seg2 = tseg2;
/* check for sjw user settings */
if (!bt->sjw || !btc->sjw_max)
{
bt->sjw = 1;
}
else
{
/* bt->sjw is at least 1 -> sanitize upper bound to sjw_max */
if (bt->sjw > btc->sjw_max)
bt->sjw = btc->sjw_max;
/* bt->sjw must not be higher than tseg2 */
if (tseg2 < bt->sjw)
bt->sjw = tseg2;
}
bt->brp = best_brp;
/* real bitrate */
bt->bitrate = CAN_CLK_FREQ / (bt->brp * (CAN_CALC_SYNC_SEG + tseg1 + tseg2));
return FCAN_SUCCESS;
}

View File

@ -0,0 +1,39 @@
/*
 * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
 *
 * SPDX-License-Identifier: Apache-2.0.
*
* @Date: 2021-04-27 15:31:44
* @LastEditTime: 2021-04-27 15:31:44
* @Description:  Description of file
* @Modify History:
* * * Ver   Who        Date         Changes
* * ----- ------     --------    --------------------------------------
*/
#include "ft_can.h"
#include "ft_parameters.h"
FCan_Config_t FCan_Config[FT_CAN_NUM] =
{
{
.InstanceId = 0, /* Id of device */
.CanBaseAddress = FT_CAN0_BASEADDR, /* Can base Address */
.IrqNum = FT_CAN0_IRQNUM,
.BaudRate = 250000,
.TxFifoDeepth = 16,
},
{
.InstanceId = 1, /* Id of device */
.CanBaseAddress = FT_CAN1_BASEADDR, /* Can base Address */
.IrqNum = FT_CAN1_IRQNUM,
.BaudRate = 250000,
.TxFifoDeepth = 16,
},
{
.InstanceId = 2, /* Id of device */
.CanBaseAddress = FT_CAN2_BASEADDR, /* Can base Address */
.IrqNum = FT_CAN2_IRQNUM,
.BaudRate = 250000,
.TxFifoDeepth = 16,
}};

View File

@ -0,0 +1,55 @@
/*
 * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
 *
 * SPDX-License-Identifier: Apache-2.0.
*
* @Date: 2021-04-27 13:52:41
* @LastEditTime: 2021-04-27 13:52:41
* @Description:  Description of file
* @Modify History:
* * * Ver   Who        Date         Changes
* * ----- ------     --------    --------------------------------------
*/
#include "ft_can_hw.h"
#include "ft_can.h"
#include "ft_mux.h"
#include "ft_parameters.h"
#include "ft_math.h"
#include "ft_assert.h"
#include "ft_debug.h"
#define CAN_HW_DEBUG_TAG "CAN_HW"
#define CAN_HW_DEBUG_I(format, ...) FT_DEBUG_PRINT_I(CAN_HW_DEBUG_TAG, format, ##__VA_ARGS__)
#define CAN_HW_DEBUG_E(format, ...) FT_DEBUG_PRINT_E(CAN_HW_DEBUG_TAG, format, ##__VA_ARGS__)
#define CAN_HW_DEBUG_W(format, ...) FT_DEBUG_PRINT_W(CAN_HW_DEBUG_TAG, format, ##__VA_ARGS__)
void FCan_Reset(FCan_t *Can_p)
{
u32 RegValue;
FCan_Config_t *Config_p;
Ft_assertVoid(Can_p != NULL);
Ft_assertVoid(Can_p->IsReady == FT_COMPONENT_IS_READLY);
Config_p = &Can_p->Config;
RegValue = FCan_ReadReg(Config_p->CanBaseAddress, FCAN_CTRL_OFFSET);
if (RegValue & FCAN_CTRL_XFER_MASK)
{
CAN_HW_DEBUG_E("FT can is not in configration mode\n");
Ft_assertVoid(0);
return;
}
FCan_WriteReg(FT_PIN_DEMUX_BASE, FT_PIN_DEMUX_REG204_OFFSET, 0x89999990); // Reuse can IO
FCan_WriteReg(Config_p->CanBaseAddress, FCAN_CTRL_OFFSET, FCAN_CTRL_RESET_MASK);
FCan_SetBit(Config_p->CanBaseAddress, FCAN_CTRL_OFFSET, FCAN_CTRL_AIME_MASK);
FCan_WriteReg(Config_p->CanBaseAddress, FCAN_ACC_ID0_MASK_OFFSET, FCAN_ACC_IDN_MASK);
FCan_WriteReg(Config_p->CanBaseAddress, FCAN_ACC_ID1_MASK_OFFSET, FCAN_ACC_IDN_MASK);
FCan_WriteReg(Config_p->CanBaseAddress, FCAN_ACC_ID2_MASK_OFFSET, FCAN_ACC_IDN_MASK);
FCan_WriteReg(Config_p->CanBaseAddress, FCAN_ACC_ID3_MASK_OFFSET, FCAN_ACC_IDN_MASK);
FCan_ClearBit(Config_p->CanBaseAddress, FCAN_CTRL_OFFSET, FCAN_CTRL_RESET_MASK);
FCan_WriteReg(Config_p->CanBaseAddress, FCAN_INTR_OFFSET, FCAN_INTR_TEIE_MASK | FCAN_INTR_REIE_MASK);
}

View File

@ -0,0 +1,161 @@
/*
 * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
 *
 * SPDX-License-Identifier: Apache-2.0.
*
* @Date: 2021-04-27 13:52:47
* @LastEditTime: 2021-04-27 13:52:47
* @Description:  Description of file
* @Modify History:
* * * Ver   Who        Date         Changes
* * ----- ------     --------    --------------------------------------
*/
#ifndef FT_CAN_HW_H
#define FT_CAN_HW_H
#include "ft_types.h"
#include "ft_io.h"
#include "ft_can.h"
/***ft CAN REGISTER offset*/
#define FCAN_CTRL_OFFSET 0x00 /* Global control register */
#define FCAN_INTR_OFFSET 0x04 /* Interrupt register */
#define FCAN_ARB_RATE_CTRL_OFFSET 0x08 /* Arbitration rate control register */
#define FCAN_DAT_RATE_CTRL_OFFSET 0x0C /* Data rate control register */
#define FCAN_ACC_ID0_OFFSET 0x10 /* Acceptance identifier0 register */
#define FCAN_ACC_ID1_OFFSET 0x14 /* Acceptance identifier1 register */
#define FCAN_ACC_ID2_OFFSET 0x18 /* Acceptance identifier2 register */
#define FCAN_ACC_ID3_OFFSET 0x1C /* Acceptance identifier3 register */
#define FCAN_ACC_ID0_MASK_OFFSET 0x20 /* Acceptance identifier0 mask register */
#define FCAN_ACC_ID1_MASK_OFFSET 0x24 /* Acceptance identifier1 mask register */
#define FCAN_ACC_ID2_MASK_OFFSET 0x28 /* Acceptance identifier2 mask register */
#define FCAN_ACC_ID3_MASK_OFFSET 0x2C /* Acceptance identifier3 mask register */
#define FCAN_XFER_STS_OFFSET 0x30 /* Transfer status register */
#define FCAN_ERR_CNT_OFFSET 0x34 /* Error counter register */
#define FCAN_FIFO_CNT_OFFSET 0x38 /* FIFO counter register */
#define FCAN_DMA_CTRL_OFFSET 0x3C /* DMA request control register */
#define FCAN_TX_FIFO_OFFSET 0x100 /* TX FIFO shadow register */
#define FCAN_RX_FIFO_OFFSET 0x200 /* RX FIFO shadow register */
/*----------------------------------------------------------------------------*/
/* CAN register bit masks - FCAN_<REG>_<BIT>_MASK */
/*----------------------------------------------------------------------------*/
/* FCAN_CTRL mask */
#define FCAN_CTRL_XFER_MASK (0x1 << 0) /* RW */ /*Transfer enable*/
#define FCAN_CTRL_TXREQ_MASK (0x1 << 1) /* RW */ /*Transmit request*/
#define FCAN_CTRL_AIME_MASK (0x1 << 2) /* RW */ /*Acceptance identifier mask enable*/
#define FCAN_CTRL_RESET_MASK (0x1 << 6)
/* FCAN_INTR mask */
#define FCAN_INTR_STATUS_MASK (0xFF << 0) /* RO */ /*the interrupt status*/
#define FCAN_INTR_BOIS_MASK (0x1 << 0) /* RO */ /*Bus off interrupt status*/
#define FCAN_INTR_PWIS_MASK (0x1 << 1) /* RO */ /*Passive warning interrupt status*/
#define FCAN_INTR_PEIS_MASK (0x1 << 2) /* RO */ /*Passive error interrupt status*/
#define FCAN_INTR_RFIS_MASK (0x1 << 3) /* RO */ /*RX FIFO full interrupt status*/
#define FCAN_INTR_TFIS_MASK (0x1 << 4) /* RO */ /*TX FIFO empty interrupt status*/
#define FCAN_INTR_REIS_MASK (0x1 << 5) /* RO */ /*RX frame end interrupt status*/
#define FCAN_INTR_TEIS_MASK (0x1 << 6) /* RO */ /*TX frame end interrupt status*/
#define FCAN_INTR_EIS_MASK (0x1 << 7) /* RO */ /*Error interrupt status*/
#define FCAN_INTR_EN_MASK (0xFF << 8) /* RO */ /*the interrupt enable*/
#define FCAN_INTR_BOIE_MASK (0x1 << 8) /* RW */ /*Bus off interrupt enable*/
#define FCAN_INTR_PWIE_MASK (0x1 << 9) /* RW */ /*Passive warning interrupt enable*/
#define FCAN_INTR_PEIE_MASK (0x1 << 10) /* RW */ /*Passive error interrupt enable*/
#define FCAN_INTR_RFIE_MASK (0x1 << 11) /* RW */ /*RX FIFO full interrupt enable*/
#define FCAN_INTR_TFIE_MASK (0x1 << 12) /* RW */ /*TX FIFO empty interrupt enable*/
#define FCAN_INTR_REIE_MASK (0x1 << 13) /* RW */ /*RX frame end interrupt enable*/
#define FCAN_INTR_TEIE_MASK (0x1 << 14) /* RW */ /*TX frame end interrupt enable*/
#define FCAN_INTR_EIE_MASK (0x1 << 15) /* RW */ /*Error interrupt enable*/
#define FCAN_INTR_BOIC_MASK (0x1 << 16) /* WO */ /*Bus off interrupt clear*/
#define FCAN_INTR_PWIC_MASK (0x1 << 17) /* WO */ /*Passive warning interrupt clear*/
#define FCAN_INTR_PEIC_MASK (0x1 << 18) /* WO */ /*Passive error interrupt clear*/
#define FCAN_INTR_RFIC_MASK (0x1 << 19) /* WO */ /*RX FIFO full interrupt clear*/
#define FCAN_INTR_TFIC_MASK (0x1 << 20) /* WO */ /*TX FIFO empty interrupt clear*/
#define FCAN_INTR_REIC_MASK (0x1 << 21) /* WO */ /*RX frame end interrupt clear*/
#define FCAN_INTR_TEIC_MASK (0x1 << 22) /* WO */ /*TX frame end interrupt clear*/
#define FCAN_INTR_EIC_MASK (0x1 << 23) /* WO */ /*Error interrupt clear*/
/* FCAN_ACC_ID(0-3)_MASK mask */
#define FCAN_ACC_IDN_MASK 0x1FFFFFFF /* WO */ /*dont care the matching */
/* FCAN_DAT_RATE_CTRL mask */
/* FCAN_ERR_CNT_OFFSET mask */
#define FCAN_ERR_CNT_RFN_MASK (0xFF << 0) /* RO */ /*Receive error counter*/
#define FCAN_ERR_CNT_TFN_MASK (0xFF << 16) /* RO */ /*Transmit error counter*/
/* FCAN_FIFO_CNT_OFFSET mask */
#define FCAN_FIFO_CNT_RFN_MASK (0xFF << 0) /* RO */ /*Receive FIFO valid data number*/
#define FCAN_FIFO_CNT_TFN_MASK (0xFF << 16) /* RO */ /*Transmit FIFO valid data number*/
#define FCAN_ERR_CNT_TFN_SHIFT 16 /* Tx Error Count shift */
#define FCAN_FIFO_CNT_TFN_SHIFT 16 /* Tx FIFO Count shift*/
#define FCAN_IDR_ID1_SHIFT 21 /* Standard Messg Identifier */
#define FCAN_IDR_ID2_SHIFT 1 /* Extended Message Identifier */
#define FCAN_IDR_SDLC_SHIFT 14
#define FCAN_IDR_EDLC_SHIFT 26
#define FCAN_ACC_IDN_SHIFT 18 /*Standard ACC ID shift*/
#define FCAN_IDR_ID2_MASK 0x0007FFFE /* Extended message ident */
#define FCAN_IDR_ID1_MASK 0xFFE00000 /* Standard msg identifier */
#define FCAN_IDR_IDE_MASK 0x00080000 /* Identifier extension */
#define FCAN_IDR_SRR_MASK 0x00100000 /* Substitute remote TXreq */
#define FCAN_IDR_RTR_MASK 0x00000001 /* Extended frames remote TX request */
#define FCAN_IDR_DLC_MASK 0x0003C000 /* Standard msg dlc */
#define FCAN_IDR_PAD_MASK 0x00003FFF /* Standard msg padding 1 */
#define FCAN_IDR_EDLC_MASK 0x3C000000 /* Extended msg dlc */
/* Can timming */
#define FCAN_TSEG1_MIN 1
#define FCAN_TSEG1_MAX 8
#define FCAN_TSEG2_MIN 1
#define FCAN_TSEG2_MAX 8
#define FCAN_SJW_MAX 4
#define FCAN_BRP_MIN 1
#define FCAN_BRP_MAX 512
#define FCAN_BRP_INC 1
#define FCAN_CALC_SYNC_SEG 1
/**
*
* This macro reads the given register.
*
* @param BaseAddr is the base address of the device.
* @param RegOffset is the register offset to be read.
*
* @return The 32-bit value of the register
*
* @note None.
*
*****************************************************************************/
#define FCan_ReadReg(BaseAddr, RegOffset) \
Ft_in32((BaseAddr) + (u32)(RegOffset))
/****************************************************************************/
/**
*
* This macro writes the given register.
*
* @param BaseAddr is the base address of the device.
* @param RegOffset is the register offset to be written.
* @param Data is the 32-bit value to write to the register.
*
* @return None.
*
* @note None.
*
*****************************************************************************/
#define FCan_WriteReg(BaseAddr, RegOffset, Data) \
Ft_out32((BaseAddr) + (u32)(RegOffset), (u32)(Data))
#define FCan_SetBit(BaseAddr, RegOffset, Data) \
Ft_setBit32((BaseAddr) + (u32)(RegOffset), (u32)(Data))
#define FCan_ClearBit(BaseAddr, RegOffset, Data) \
Ft_clearBit32((BaseAddr) + (u32)(RegOffset), (u32)(Data))
void FCan_Reset(FCan_t *Can_p);
#endif // !

View File

@ -0,0 +1,118 @@
/*
 * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
 *
 * SPDX-License-Identifier: Apache-2.0.
*
* @Date: 2021-04-29 10:40:47
* @LastEditTime: 2021-04-29 10:40:47
* @Description:  Description of file
* @Modify History:
* * * Ver   Who        Date         Changes
* * ----- ------     --------    --------------------------------------
*/
#include "ft_can.h"
#include "ft_can_hw.h"
#include "ft_assert.h"
#include "ft_types.h"
ft_error_t FCan_SetHandler(FCan_t *Can_p, u32 HandlerType, FCan_irqHandler_t IrqCallBackFunc, void *IrqCallBackRef)
{
ft_error_t status = FCAN_SUCCESS;
Ft_assertNonvoid(Can_p != NULL);
Ft_assertNonvoid(Can_p->IsReady == FT_COMPONENT_IS_READLY);
switch (HandlerType)
{
case FCAN_HANDLER_SEND:
Can_p->SendHandler = IrqCallBackFunc;
Can_p->SendRef = IrqCallBackRef;
break;
case FCAN_HANDLER_RECV:
Can_p->RecvHandler = IrqCallBackFunc;
Can_p->RecvRef = IrqCallBackRef;
break;
case FCAN_HANDLER_ERROR:
Can_p->ErrorHandler = IrqCallBackFunc;
Can_p->ErrorRef = IrqCallBackRef;
break;
default:
status = FCAN_FAILURE;
}
return status;
}
static void FCan_TxInterrupt(FCan_t *Can_p)
{
FCan_Config_t *Config_p = &Can_p->Config;
FCan_SetBit(Config_p->CanBaseAddress, FCAN_INTR_OFFSET, FCAN_INTR_TEIC_MASK | FCAN_INTR_REIC_MASK);
if (0 != Can_p->TxFifoCnt)
{
Can_p->TxFifoCnt--;
FCan_ClearBit(Config_p->CanBaseAddress, FCAN_CTRL_OFFSET, FCAN_CTRL_XFER_MASK);
FCan_SetBit(Config_p->CanBaseAddress, FCAN_CTRL_OFFSET, FCAN_CTRL_TXREQ_MASK);
FCan_SetBit(Config_p->CanBaseAddress, FCAN_CTRL_OFFSET, FCAN_CTRL_XFER_MASK);
}
else
{
if (Can_p->SendHandler)
{
Can_p->SendHandler(Can_p->SendRef);
}
}
}
static void FCan_ErrorInterrupt(FCan_t *Can_p)
{
if (Can_p->ErrorHandler)
{
Can_p->ErrorHandler(Can_p->ErrorRef);
}
}
static void FCan_RxInterrupt(FCan_t *Can_p)
{
if (Can_p->RecvHandler)
{
Can_p->RecvHandler(Can_p->RecvRef);
}
}
void FCan_IntrHandler(void *InstancePtr)
{
u32 Irq;
FCan_t *Can_p = (FCan_t *)InstancePtr;
FCan_Config_t *Config_p;
Ft_assertVoid(Can_p != NULL);
Ft_assertVoid(Can_p->IsReady == FT_COMPONENT_IS_READLY);
Config_p = &Can_p->Config;
Irq = FCan_ReadReg(Config_p->CanBaseAddress, FCAN_INTR_OFFSET);
if (0 == Irq)
{
return;
}
/* Check for the type of error interrupt and Processing it */
if (Irq & FCAN_INTR_TEIS_MASK)
{
Irq &= ~FCAN_INTR_REIS_MASK;
FCan_TxInterrupt(Can_p);
}
if (Irq & (FCAN_INTR_EIS_MASK | FCAN_INTR_RFIS_MASK |
FCAN_INTR_BOIS_MASK | FCAN_INTR_PEIS_MASK | FCAN_INTR_PWIS_MASK))
{
FCan_SetBit(Config_p->CanBaseAddress, FCAN_INTR_OFFSET, (FCAN_INTR_EIC_MASK | FCAN_INTR_RFIC_MASK | FCAN_INTR_BOIC_MASK | FCAN_INTR_PEIC_MASK | FCAN_INTR_PWIC_MASK));
FCan_ErrorInterrupt(Can_p);
}
if (Irq & FCAN_INTR_REIS_MASK)
{
FCan_SetBit(Config_p->CanBaseAddress, FCAN_INTR_OFFSET, FCAN_INTR_REIE_MASK);
FCan_RxInterrupt(Can_p);
FCan_SetBit(Config_p->CanBaseAddress, FCAN_INTR_OFFSET, FCAN_INTR_REIC_MASK);
FCan_SetBit(Config_p->CanBaseAddress, FCAN_INTR_OFFSET, FCAN_INTR_REIE_MASK);
}
}

View File

@ -0,0 +1,40 @@
/*
 * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
 *
 * SPDX-License-Identifier: Apache-2.0.
*
* @Date: 2021-04-27 15:31:57
* @LastEditTime: 2021-04-27 15:31:57
* @Description:  Description of file
* @Modify History:
* * * Ver   Who        Date         Changes
* * ----- ------     --------    --------------------------------------
*/
#include "ft_can.h"
#include "ft_parameters.h"
extern FCan_Config_t FCan_Config[FT_CAN_NUM];
/**
* @name:
* @msg:
* @in param:
* @return {*}
* @param {u32} InstanceId
*/
FCan_Config_t *FCan_LookupConfig(u32 InstanceId)
{
FCan_Config_t *CfgPtr = NULL;
u32 Index;
for (Index = 0; Index < (u32)FT_CAN_NUM; Index++)
{
if (FCan_Config[Index].InstanceId == InstanceId)
{
CfgPtr = &FCan_Config[Index];
break;
}
}
return (FCan_Config_t *)CfgPtr;
}

View File

@ -0,0 +1,109 @@
/*
 * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
 *
 * SPDX-License-Identifier: Apache-2.0.
 *
* @Date: 2021-04-07 09:53:07
* @LastEditTime: 2021-05-25 16:43:14
* @Description:  This files is for gmac ctrl
*
* @Modify History:
* Ver   Who        Date         Changes
* ----- ------     --------    --------------------------------------
*/
#include "ft_gmac.h"
#include "ft_gmac_hw.h"
#include "ft_assert.h"
#include "ft_io.h"
#include "ft_status.h"
#include "ft_printf.h"
#include "ft_parameters.h"
static void Ft_Gmac_StubHandler(void *args)
{
Ft_assertVoidAlways();
}
static void Ft_Gmac_StubErrorHandler(void *CallBackRef, u32 ErrorWord)
{
// Ft_assertVoidAlways();
}
s32 Ft_Gmac_HwInitialize(Ft_Gmac_t *Gmac)
{
Ft_assertNonvoid(Gmac != NULL);
Ft_assertNonvoid(Gmac->IsReady == FT_COMPONENT_IS_READLY);
return FGmac_InitializeHw(&Gmac->Config);
}
s32 Ft_GmacCfgInitialize(Ft_Gmac_t *Gmac, FGmac_Config_t *Config)
{
Ft_assertNonvoid(Gmac != NULL);
Ft_assertNonvoid(Config != NULL);
Gmac->Config = *Config;
Gmac->IsReady = FT_COMPONENT_IS_READLY;
FGmac_SetHandler(Gmac, FT_GMAC_TX_COMPLETE_CB_ID, Ft_Gmac_StubHandler, Gmac);
FGmac_SetHandler(Gmac, FT_GMAC_RX_COMPLETE_CB_ID, Ft_Gmac_StubHandler, Gmac);
FGmac_SetHandler(Gmac, FT_GMAC_DMA_ERROR_CB_ID, Ft_Gmac_StubErrorHandler, Gmac);
return FST_SUCCESS;
}
s32 Ft_Gmac_Start(Ft_Gmac_t *Gmac)
{
FGmac_Config_t *Config = NULL;
Ft_assertNonvoid(Gmac != NULL);
Ft_assertNonvoid(Gmac->IsReady == FT_COMPONENT_IS_READLY);
Config = &Gmac->Config;
FGmac_DMAReceptionTransmissionEnable(Config);
FGmac_ReceptionTransmissionEnable(Config);
/* Clear Tx and Rx process stopped flags */
Ft_out32(Gmac->Config.BaseAddress + DMA_INTR_ENA_OFFSET, DMA_INTR_ENA_RIE | DMA_INTR_ENA_AIE | DMA_INTR_ENA_NIE);
return FST_SUCCESS;
}
s32 Ft_Gmac_Stop(Ft_Gmac_t *Gmac)
{
FGmac_Config_t *Config = NULL;
Ft_assertNonvoid(Gmac != NULL);
Ft_assertNonvoid(Gmac->IsReady == FT_COMPONENT_IS_READLY);
Config = &Gmac->Config;
FGmac_TransmissionDisable(Config);
FGmac_ReceptionDisable(Config);
FGmac_DMATransmissionDisable(Config);
FGmac_DMAReceptionDisable(Config);
return FST_SUCCESS;
}
void Ft_Gmac_Phy_Debug(Ft_Gmac_t *Gmac)
{
Ft_printf("\r\n ****************************** \r\n");
}
void Ft_Gmac_UseDefaultMacAddr(Ft_Gmac_t *Gmac, u8 *MacAddr)
{
u32 MacAddrLo;
u32 MacAddrHi;
FGmac_Config_t *pConfig;
Ft_assertNoneReturn(Gmac != NULL);
pConfig = &Gmac->Config;
MacAddrLo = Ft_in32(pConfig->BaseAddress + GMAC_MAC_ADDR0_LOWER16BIT_OFFSET);
MacAddrHi = Ft_in32(pConfig->BaseAddress + GMAC_MAC_ADDR0_UPPER16BIT_OFFSET);
MacAddr[0] = MacAddrLo & 0xFF;
MacAddr[1] = (MacAddrLo >> 8) & 0xFF;
MacAddr[2] = (MacAddrLo >> 16) & 0xFF;
MacAddr[3] = (MacAddrLo >> 24) & 0xFF;
MacAddr[4] = MacAddrHi & 0xFF;
MacAddr[5] = (MacAddrHi >> 8) & 0xFF;
}

View File

@ -0,0 +1,319 @@
/*
 * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
 *
 * SPDX-License-Identifier: Apache-2.0.
 *
* @Date: 2021-04-07 09:53:07
* @LastEditTime: 2021-05-24 14:32:56
* @Description:  This files is for
*
* @Modify History:
* Ver   Who        Date         Changes
* ----- ------     --------    --------------------------------------
* 1.00a hh 2021-02-05 First release
*/
#ifndef FT_GMAC_H
#define FT_GMAC_H
#include "ft_types.h"
#define GMAC_INC_DESC(x, y) (x) = (((x) + 1) % y)
/**
* @name: Callback invoked when frame(s) have been sent or received in interrupt
* driven DMA mode .to set the send callback ,invoke FGmac_SetHandler()
* @msg:
* @param {void} *CallBackRef
* @return {*}
*/
typedef void (*FGmac_IntrCallback_t)(void *CallBackRef);
/**
* @name: FGmac_ErrIntrCallback_t
* @msg: Callback whem asynchronous error occurs. To set this callback, invoke
* FGmac_ErrIntrCallback_t .
* @param {void} *CallBackRef
* @param {u32} ErrorWord definition varies with Error
* @return {*}
*/
typedef void (*FGmac_ErrIntrCallback_t)(void *CallBackRef, u32 ErrorWord);
/**
*
*
*/
typedef void (*Ft_Gmac_MacPhyStatus_Callback)(void *CallBackRef, u32 MacPhyStatus);
/** GMAC_SPEED */
#define GMAC_SPEED_10M 0x00000001U
#define GMAC_SPEED_100M 0x00000002U
#define GMAC_SPEED_1000M 0x00000004U
#define IS_RIGHT_SPEED()
/* GMAC_AutoNegotiation */
#define GMAC_AUTONEGOTIATION_ENABLE 0x00000001U
#define GMAC_AUTONEGOTIATION_DISABLE 0x00000000U
/* GMAC_Duplex_Mode */
#define GMAC_MODE_FULLDUPLEX 0x00000001U
#define GMAC_MODE_HALFDUPLEX 0x00000000U
/* GMAC_Rx_Mode */
#define GMAC_RXPOLLING_MODE 0x00000000U
#define GMAC_RXINTERRUPT_MODE 0x00000001U
/* GMAC_Checksum_Mode */
#define GMAC_CHECKSUM_BY_SOFTWARE 0x00000000U
#define GMAC_CHECKSUM_BY_HARDWARE 0x00000001U
/* GMAC_Media_Interface */
#define GMAC_MEDIA_INTERFACE_RGMII 0x00000000U
#define GMAC_MEDIA_INTERFACE_MII 0x00000001U
/* Gmac Error value */
#define GMAC_ERROR_TRANSMIT_PROCESS_STOPPED 0x00000001U
#define GMAC_ERROR_TRANSMIT_UNAVAILABLE_STATUS 0x00000002U
#define GMAC_ERROR_TRANSMIT_JABBER_TIMEOUT 0x00000004U
#define GMAC_ERROR_RECEIVE_FIFO_OVERFLOW 0x00000008U
#define GMAC_ERROR_TRANSMIT_UNDERFLOW 0x00000010U
#define GMAC_ERROR_RECEIVE_BUFFER_UNAVAILABLE 0x00000020U
#define GMAC_ERROR_RECEIVE_PROCESS_STOPPED 0x00000040U
#define GMAC_ERROR_RECEIVE_WATCHDOG_TIMEOUT 0x00000080U
#define GMAC_ERROR_EARLY_TRANSMIT_INTERRUPT 0x000000100U
#define GMAC_ERROR_FATAL_BUS_ERROR 0x000000200U
#define GMAC_ERROR_UNDEFINED 0x000000400U
typedef enum
{
FT_GMAC_TX_COMPLETE_CB_ID = 0x01U, /*!< Gmac Tx Complete Callback ID */
FT_GMAC_RX_COMPLETE_CB_ID = 0x02U, /*!< Gmac Rx Complete Callback ID */
FT_GMAC_DMA_ERROR_CB_ID = 0x03U, /*!< Gmac DMA Error Callback ID */
FT_GMAC_MAC_PHY_STATUS_CB_ID = 0x04U, /*!< */
} FGmac_IsrCallbackSelect_t;
/* Gmac DMA Descriptors data structure definition */
typedef struct
{
volatile u32 Status; /*!< Status */
u32 Control; /*!< Control and Buffer1, Buffer2 lengths */
u32 Buffer1Addr; /*!< Buffer1 address pointer */
u32 Buffer2NextDescAddr; /*!< Buffer2 or next descriptor address pointer */
} FGmac_DmaDesc_t;
/* Received Frame Informations structure definition */
typedef struct
{
FGmac_DmaDesc_t *FSRxDesc; /*!< First Segment Rx Desc */
FGmac_DmaDesc_t *LSRxDesc; /*!< Last Segment Rx Desc */
u32 SegCount; /*!< Segment count */
u32 length; /*!< Frame length */
u32 buffer; /*!< Frame buffer */
} FGmac_DmaRxFrameInfos;
typedef struct
{
u32 InstanceId; /* Id of device */
uintptr_t CommonAddress; /* Gmac Common Register */
uintptr_t BaseAddress; /* Physical base address of Mac Private Address */
u32 IRQ_NUM;
u32 IRQPriority;
s32 PhyAddr; /* Phy Ic Addre1 ,-1 is need to auto check*/
u32 clkMDC; /* MDC clock access PHY. [1.0MHz ~2.5MHz] */
u32 AutoNegotiation; /* Selects or not the AutoNegotiation mode for the external PHY
The AutoNegotiation allows an automatic setting of the Speed (10/100/1000Mbps)
and the mode (half/full-duplex).
This parameter can be a value of @ref GMAC_AutoNegotiation */
u32 Speed; /* Sets the Ethernet speed: 10/100/1000 Mbps.
This parameter can be a value of @ref GMAC_SPEED */
u32 DuplexMode; /* Selects the MAC duplex mode: Half-Duplex or Full-Duplex mode
This parameter can be a value of @ref GMAC_Duplex_Mode */
u32 RxMode; /* Selects the Ethernet Rx mode: Polling mode, Interrupt mode.
This parameter can be a value of @ref GMAC_Rx_Mode */
u32 ChecksumMode; /* Selects if the checksum is check by hardware or by software.
This parameter can be a value of @ref GMAC_Checksum_Mode */
u32 MediaInterface; /* Selects the media-independent interface or the reduced media-independent interface.
This parameter can be a value of @ref GMAC_Media_Interface */
u8 MacAddr[6]; /* 6 bytes Mac address */
} FGmac_Config_t;
/* Only for Dma ring structure */
struct DescRingData
{
u32 DescIndex; /* For Current Desc position */
u32 DescBufIndex; /* For Current Desc buffer buf position */
u32 DescMaxNumber; /* Max Number for Desc and Desc buffer */
u8 *DescBufBase; /* Desc buffer Base */
};
typedef struct
{
FGmac_Config_t Config; /* Hardware configuration */
u32 IsReady; /* Device is initialised and ready */
u32 Options; /* Current options word */
FGmac_DmaDesc_t *RxDesc; /*!< Rx descriptor to Get */
struct DescRingData RxDescRingData;
FGmac_DmaDesc_t *TxDesc; /*!< Tx descriptor to Set */
struct DescRingData TxDescRingData;
FGmac_IntrCallback_t SendHandler;
FGmac_IntrCallback_t RecvHandler;
Ft_Gmac_MacPhyStatus_Callback StatusHandler;
void *SendArgs;
void *RecvArgs;
void *StatusArgs;
FGmac_ErrIntrCallback_t ErrorHandler;
void *ErrorArgs;
FGmac_DmaRxFrameInfos DMARxFrameInfos; /* Only for chain structure */
} Ft_Gmac_t;
/**
* @name: FGmac_DmaRxDescRingInit
* @msg: DMA ring结构下的初始化
* @param {Ft_Gmac_t} *Gmac Gmac对象
* @param {FGmac_DmaDesc_t} *DMARxDescTab DMA
* @param {u8} *RxBuff DMA
* @param {u32} DescBufPerLength
* @param {u32} RxBuffCount
* @return {s32} Common_status
*/
s32 FGmac_DmaRxDescRingInit(Ft_Gmac_t *Gmac,
FGmac_DmaDesc_t *DMATxDescTab,
u8 *TxBuff,
u32 DescBufPerLength,
u32 TxBuffCount);
/**
* @name: FGmac_DmaTxDescRingInit
* @msg: DMA ring结构下的初始化
* @param {Ft_Gmac_t} *Gmac Gmac对象
* @param {FGmac_DmaDesc_t} *DMATxDescTab DMA
* @param {u8} *TxBuff DMA
* @param {u32} DescBufPerLength
* @param {u32} TxBuffCount
* @return {s32} Common_status
*/
s32 FGmac_DmaTxDescRingInit(Ft_Gmac_t *Gmac,
FGmac_DmaDesc_t *DMATxDescTab,
u8 *TxBuff,
u32 DescBufPerLength,
u32 TxBuffCount);
/**
* @name: FGmac_TransmitframeRingPoll
* @msg: DMA发送表述符
* @param {Ft_Gmac_t} *Gmac Gmac对象
* @param {uint32_t} FrameLength
* @return {s32} Common_status
*/
s32 FGmac_TransmitframeRingPoll(Ft_Gmac_t *Gmac, uint32_t FrameLength);
/**
* @name: FGmac_RingGetReceivedFrame_IT
* @msg: ring结构的DMA接收符中是否有完整的数据包
* @param {Ft_Gmac_t} *Gmac Gmac对象
* @return {s32} Common_status
*/
s32 FGmac_RingGetReceivedFrame_IT(Ft_Gmac_t *Gmac);
/**
* @name: FGmac_ResumeTransmission
* @msg: DMA_STATUS_TU DMA
* @param {Ft_Gmac_t} *Gmac Gmac对象
* @return {void}
*/
void FGmac_ResumeTransmission(Ft_Gmac_t *Gmac);
/**
* @name: FGmac_SetTransmitUnderflow
* @msg: DMA_STATUS_UNF DMA
* @param {Ft_Gmac_t} *Gmac Gmac对象
* @return {void}
*/
void FGmac_SetTransmitUnderflow(Ft_Gmac_t *Gmac);
/**
* @name: FGmac_ResumeTransmissionReception
* @msg: DMA_STATUS_RU DMA
* @param {Ft_Gmac_t} *Gmac
* @return {void}
*/
void FGmac_ResumeTransmissionReception(Ft_Gmac_t *Gmac);
/**
* @name: Ft_Gmac_LookupConfig
* @msg: Gmac
* @param {u32} InstanceId Gmac
* @return {FGmac_Config_t *} Gmac的静态配置
*/
FGmac_Config_t *Ft_Gmac_LookupConfig(u32 InstanceId);
/**
* @name: Ft_Gmac_HwInitialize
* @msg: Gmac Mac Phy
* @param {Ft_Gmac_t} *Gmac Gmac对象
* @return {s32} Common_status
*/
s32 Ft_Gmac_HwInitialize(Ft_Gmac_t *Gmac);
/**
* @name: Ft_GmacCfgInitialize
* @msg:
* @param {Ft_Gmac_t} *Gmac Gmac对象
* @param {FGmac_Config_t} *Config
* @return {s32} Common_status
*/
s32 Ft_GmacCfgInitialize(Ft_Gmac_t *Gmac, FGmac_Config_t *Config);
/**
* @name: Ft_Gmac_Start
* @msg: Gmac
* @param {Ft_Gmac_t} *Gmac Gmac对象
* @return {s32} Common_status
*/
s32 Ft_Gmac_Start(Ft_Gmac_t *Gmac);
/**
* @name: Ft_Gmac_Stop
* @msg: Gmac
* @param {Ft_Gmac_t} *Gmac Gmac对象
* @return {s32} Common_status
*/
s32 Ft_Gmac_Stop(Ft_Gmac_t *Gmac);
/**
* @name: FGmac_IntrHandler
* @msg: Gmac Gmac
* @param {void} *Args Ft_Gmac_t *Gmac
* @return {void}
*/
void FGmac_IntrHandler(void *Args);
/**
* @name: FGmac_SetHandler
* @msg: SelectIndex
* @param {Ft_Gmac_t} *Gmac Gmac对象
* @param {FGmac_IsrCallbackSelect_t} SelectIndex
* @param {void} *FuncPtr
* @param {void} *Args
* @return {s32} Common_status
*/
s32 FGmac_SetHandler(Ft_Gmac_t *Gmac, FGmac_IsrCallbackSelect_t SelectIndex, void *FuncPtr, void *Args);
void Ft_Gmac_Phy_Debug(Ft_Gmac_t *Gmac);
/**
* @name: Ft_Gmac_UseDefaultMacAddr
* @msg: uboot的模式之下使Mac0配置参数
* @in param{Ft_Gmac_t *}: Gmac对象
* @out param{u8 *}: Mac参数
* @return {None}:
*/
void Ft_Gmac_UseDefaultMacAddr(Ft_Gmac_t *Gmac, u8 *MacAddr);
#endif // !GMAC_H

View File

@ -0,0 +1,357 @@
/*
 * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
 *
 * SPDX-License-Identifier: Apache-2.0.
 *
* @Date: 2021-04-07 09:53:07
* @LastEditTime: 2021-05-25 16:42:13
* @Description:  This files is for gmac description
*
* @Modify History:
* Ver   Who        Date         Changes
* ----- ------     --------    --------------------------------------
*/
#include "ft_gmac_desc.h"
#include "ft_gmac_hw.h"
#include "ft_parameters.h"
#include "ft_io.h"
#include "ft_status.h"
#include "ft_assert.h"
#include "ft_cache.h"
#include "ft_debug.h"
#include <string.h>
#define GMAC_DESC_DEBUG_TAG "GMAC_DESC"
#define GMAC_DESC_DEBUG_I(format, ...) FT_DEBUG_PRINT_I(GMAC_DESC_DEBUG_TAG, format, ##__VA_ARGS__)
#define GMAC_DESC_DEBUG_E(format, ...) FT_DEBUG_PRINT_E(GMAC_DESC_DEBUG_TAG, format, ##__VA_ARGS__)
#define GMAC_DESC_DEBUG_W(format, ...) FT_DEBUG_PRINT_W(GMAC_DESC_DEBUG_TAG, format, ##__VA_ARGS__)
void FGmac_ResumeTransmission(Ft_Gmac_t *Gmac)
{
/* When Tx Buffer unavailable flag is set: clear it and resume transmission */
if ((Ft_in32(Gmac->Config.BaseAddress + DMA_STATUS_OFFSET) & DMA_STATUS_TU) == DMA_STATUS_TU)
{
/* Clear TBUS GMAC DMA flag */
Ft_out32(Gmac->Config.BaseAddress + DMA_STATUS_OFFSET, DMA_STATUS_TU);
/* Resume DMA transmission*/
Ft_out32(Gmac->Config.BaseAddress + DMA_XMT_POLL_DEMAND_OFFSET, 0xff);
}
}
void FGmac_SetTransmitUnderflow(Ft_Gmac_t *Gmac)
{
/* When Tx Buffer unavailable flag is set: clear it and resume transmission */
if ((Ft_in32(Gmac->Config.BaseAddress + DMA_STATUS_OFFSET) & DMA_STATUS_UNF) == DMA_STATUS_UNF)
{
/* Clear TBUS GMAC DMA flag */
Ft_out32(Gmac->Config.BaseAddress + DMA_STATUS_OFFSET, DMA_STATUS_UNF);
/* Resume DMA transmission*/
Ft_out32(Gmac->Config.BaseAddress + DMA_XMT_POLL_DEMAND_OFFSET, 0xff);
}
}
s32 FGmac_DMATxDescChainInit(Ft_Gmac_t *Gmac, FGmac_DmaDesc_t *DMATxDescTab, u8 *TxBuff, u32 TxBuffCount)
{
u32 i;
FGmac_DmaDesc_t *TxDesc;
Ft_assertNonvoid(Gmac != NULL);
Ft_assertNonvoid(Gmac->IsReady == FT_COMPONENT_IS_READLY);
/* Make Each DmaTx descriptor with initialized value*/
for (i = 0; i < TxBuffCount; i++)
{
TxDesc = DMATxDescTab + i;
TxDesc->Control = DMA_TDES1_SECOND_ADDRESS_CHAINED;
TxDesc->Buffer1Addr = (u32)(&TxBuff[i * GMAC_MAX_PACKET_SIZE]);
/* Initialize the next descriptor with the Next Descriptor Polling Enable */
if (i < (TxBuffCount - 1))
{
/* Set next descriptor address register with next descriptor base address */
TxDesc->Buffer2NextDescAddr = (u32)(DMATxDescTab + i + 1);
Ft_printf(" Buffer2NextDescAddr %x \r\n", TxDesc->Buffer2NextDescAddr);
}
else
{
/* For last descriptor, set next descriptor address register equal to the first descriptor base address */
TxDesc->Buffer2NextDescAddr = (u32)DMATxDescTab;
Ft_printf(" Buffer2NextDescAddr %x \r\n", TxDesc->Buffer2NextDescAddr);
}
}
Ft_printf("DMATxDescTab addr is %x", DMATxDescTab);
return FST_SUCCESS;
}
s32 FGmac_DmaTxDescRingInit(Ft_Gmac_t *Gmac, FGmac_DmaDesc_t *DMATxDescTab, u8 *TxBuff, u32 DescBufPerLength, u32 TxBuffCount)
{
u32 i;
FGmac_DmaDesc_t *TxDesc;
Ft_assertNonvoid(Gmac != NULL);
Ft_assertNonvoid(Gmac->IsReady == FT_COMPONENT_IS_READLY);
memset(&Gmac->TxDescRingData, 0, sizeof(Gmac->TxDescRingData));
Gmac->TxDescRingData.DescMaxNumber = TxBuffCount;
memset(DMATxDescTab, 0, sizeof(FGmac_DmaDesc_t) * TxBuffCount);
DMATxDescTab[TxBuffCount - 1].Control |= DMA_TDES1_END_RING;
for (i = 0; i < TxBuffCount; i++)
{
TxDesc = DMATxDescTab + i;
FCache_cpuDcacheInvalidate(&TxBuff[i * DescBufPerLength], DescBufPerLength);
TxDesc->Buffer1Addr = (u32)(&TxBuff[i * DescBufPerLength]);
}
Ft_out32(Gmac->Config.BaseAddress + DMA_TX_BASE_ADDR_OFFSET, (u32)DMATxDescTab);
return FST_SUCCESS;
}
s32 FGmac_TransmitframeRingPoll(Ft_Gmac_t *Gmac, uint32_t FrameLength)
{
u32 Size = 0U;
u32 i = 0U;
u32 BufCount = 0U;
FGmac_DmaDesc_t *TxDesc;
if (0U == FrameLength)
{
return FST_SUCCESS;
}
if (FrameLength > GMAC_MAX_PACKET_SIZE)
{
BufCount = FrameLength / GMAC_MAX_PACKET_SIZE;
if (FrameLength % GMAC_MAX_PACKET_SIZE)
{
BufCount++;
}
}
else
{
BufCount = 1U;
}
if (BufCount == 1U)
{
TxDesc = &Gmac->TxDesc[Gmac->TxDescRingData.DescIndex];
/* Set LAST and FIRST segment */
TxDesc->Control |= (DMA_TDES1_FIRST_SEGMENT | DMA_TDES1_LAST_SEGMENT);
/* Set frame size */
TxDesc->Control &= ~(DMA_TDES1_BUFFER1_SIZE_MASK);
TxDesc->Control |= (FrameLength & DMA_TDES1_BUFFER1_SIZE_MASK);
/* Set Own bit of the Tx descriptor Status: gives the buffer back to ETHERNET DMA */
TxDesc->Status |= (DMA_TDES0_OWN);
GMAC_INC_DESC(Gmac->TxDescRingData.DescIndex, Gmac->TxDescRingData.DescMaxNumber);
}
else
{
for (i = 0U; i < BufCount; i++)
{
TxDesc = &Gmac->TxDesc[Gmac->TxDescRingData.DescIndex];
/* Clear FIRST and LAST segment bits */
TxDesc->Control &= ~(DMA_TDES1_FIRST_SEGMENT | DMA_TDES1_LAST_SEGMENT);
if (i == 0U)
{
/* Setting the first segment bit */
TxDesc->Control |= DMA_TDES1_FIRST_SEGMENT;
}
/* Program size */
TxDesc->Control &= ~(DMA_TDES1_BUFFER1_SIZE_MASK);
TxDesc->Control |= (GMAC_MAX_PACKET_SIZE & DMA_TDES1_BUFFER1_SIZE_MASK);
if (i == (BufCount - 1U))
{
/* Setting the last segment bit */
TxDesc->Control |= (DMA_TDES1_LAST_SEGMENT);
Size = FrameLength - (BufCount - 1U) * GMAC_MAX_PACKET_SIZE;
TxDesc->Control &= ~(DMA_TDES1_BUFFER1_SIZE_MASK);
TxDesc->Control |= (Size & DMA_TDES1_BUFFER1_SIZE_MASK);
}
/* Set Own bit of the Tx descriptor Status: gives the buffer back to ETHERNET DMA */
TxDesc->Status |= (DMA_TDES0_OWN);
GMAC_INC_DESC(Gmac->TxDescRingData.DescIndex, Gmac->TxDescRingData.DescMaxNumber);
}
}
FGmac_ResumeTransmission(Gmac);
return FST_SUCCESS;
}
s32 FGmac_DMARxDescChainInit(Ft_Gmac_t *Gmac, FGmac_DmaDesc_t *DMARxDescTab, u8 *RxBuff, u32 RxBuffCount)
{
u32 i;
FGmac_DmaDesc_t *RxDesc;
Ft_assertNonvoid(Gmac != NULL);
Ft_assertNonvoid(Gmac->IsReady == FT_COMPONENT_IS_READLY);
for (i = 0; i < RxBuffCount; i++)
{
RxDesc = DMARxDescTab + i;
/* Set Own bit of the Rx descriptor Status */
RxDesc->Status = DMA_RDES0_OWN;
/* Set Buffer1 size and Second Address Chained bit */
RxDesc->Control = DMA_RDES1_BUFFER1_SIZE_MASK & (u32)(GMAC_MAX_PACKET_SIZE);
RxDesc->Control |= DMA_RDES1_SECOND_ADDRESS_CHAINED;
/* Set Buffer1 address pointer */
RxDesc->Buffer1Addr = (u32)(&RxBuff[i * GMAC_MAX_PACKET_SIZE]);
/* Initialize the next descriptor with the Next Descriptor Polling Enable */
if (i < (RxBuffCount - 1))
{
/* Set next descriptor address register with next descriptor base address */
RxDesc->Buffer2NextDescAddr = (u32)(DMARxDescTab + i + 1);
}
else
{
/* For last descriptor, set next descriptor address register equal to the first descriptor base address */
RxDesc->Buffer2NextDescAddr = (u32)(DMARxDescTab);
}
// Ft_printf("rx Buffer2NextDescAddr %x \r\n", RxDesc->Buffer2NextDescAddr);
}
Ft_out32(Gmac->Config.BaseAddress + DMA_RCV_BASE_ADDR_OFFSET, (u32)DMARxDescTab);
return FST_SUCCESS;
}
s32 FGmac_DmaRxDescRingInit(Ft_Gmac_t *Gmac, FGmac_DmaDesc_t *DMARxDescTab, u8 *RxBuff, u32 DescBufPerLength, u32 RxBuffCount)
{
u32 i;
FGmac_DmaDesc_t *RxDesc;
Ft_assertNonvoid(Gmac != NULL);
Ft_assertNonvoid(Gmac->IsReady == FT_COMPONENT_IS_READLY);
memset(&Gmac->RxDescRingData, 0, sizeof(Gmac->RxDescRingData));
Gmac->RxDescRingData.DescMaxNumber = RxBuffCount;
memset(DMARxDescTab, 0, sizeof(FGmac_DmaDesc_t) * RxBuffCount);
for (i = 0; i < RxBuffCount; i++)
{
RxDesc = DMARxDescTab + i;
/* Set Own bit of the Rx descriptor Status */
RxDesc->Status = DMA_RDES0_OWN;
/* Set Buffer1 size and Second Address Chained bit */
RxDesc->Control = DMA_RDES1_BUFFER1_SIZE_MASK & (u32)(DescBufPerLength);
/* Set Buffer1 address pointer */
FCache_cpuDcacheInvalidate(&RxBuff[i * DescBufPerLength], DescBufPerLength);
RxDesc->Buffer1Addr = (u32)(&RxBuff[i * DescBufPerLength]);
if (i == (RxBuffCount - 1))
{
RxDesc->Control |= DMA_RDES1_END_RING;
}
}
Ft_out32(Gmac->Config.BaseAddress + DMA_RCV_BASE_ADDR_OFFSET, (u32)DMARxDescTab);
return FST_SUCCESS;
}
void FGmac_ResumeTransmissionReception(Ft_Gmac_t *Gmac)
{
/* When Rx Buffer unavailable flag is set: clear it and resume transmission */
if ((Ft_in32(Gmac->Config.BaseAddress + DMA_STATUS_OFFSET) & DMA_STATUS_RU) == DMA_STATUS_RU)
{
/* Clear RBUS GMAC DMA flag */
Ft_out32(Gmac->Config.BaseAddress + DMA_STATUS_OFFSET, DMA_STATUS_RU);
/* Resume DMA transmission*/
Ft_out32(Gmac->Config.BaseAddress + DMA_RCV_POLL_DEMAND_OFFSET, 0xff);
}
}
s32 FGmac_RingGetReceivedFrame_IT(Ft_Gmac_t *Gmac)
{
u32 DescriptorsCounter = 0U;
FGmac_DmaDesc_t *RxDesc;
RxDesc = &Gmac->RxDesc[Gmac->RxDescRingData.DescIndex];
while (((RxDesc->Status & DMA_RDES0_OWN) == 0) && DescriptorsCounter < Gmac->RxDescRingData.DescMaxNumber)
{
DescriptorsCounter++;
/* Check if first segment in frame */
if ((RxDesc->Status & (DMA_RDES0_FIRST_DESCRIPTOR | DMA_RDES0_LAST_DESCRIPTOR)) == (u32)DMA_RDES0_FIRST_DESCRIPTOR)
{
// GMAC_DESC_DEBUG_I("find first frame");
Gmac->RxDescRingData.DescBufIndex = Gmac->RxDescRingData.DescIndex;
/* Point to next descriptor */
GMAC_INC_DESC(Gmac->RxDescRingData.DescIndex, Gmac->RxDescRingData.DescMaxNumber);
RxDesc = &Gmac->RxDesc[Gmac->RxDescRingData.DescIndex];
} /* Check if intermediate segment */
else if ((RxDesc->Status & (DMA_RDES0_FIRST_DESCRIPTOR | DMA_RDES0_LAST_DESCRIPTOR)) == 0)
{
// GMAC_DESC_DEBUG_I("find invaild frame");
/* Point to next descriptor */
GMAC_INC_DESC(Gmac->RxDescRingData.DescIndex, Gmac->RxDescRingData.DescMaxNumber);
RxDesc = &Gmac->RxDesc[Gmac->RxDescRingData.DescIndex];
} /* Should be last segment */
else
{
Gmac->RxDescRingData.DescBufIndex = Gmac->RxDescRingData.DescIndex;
GMAC_INC_DESC(Gmac->RxDescRingData.DescIndex, Gmac->RxDescRingData.DescMaxNumber);
return FST_SUCCESS;
}
}
return FST_FAILURE;
}
s32 FGmac_GetReceivedFrame(Ft_Gmac_t *Gmac)
{
u32 FrameLength = 0U;
/* Check if segment is not owned by DMA */
if ((Gmac->RxDesc->Status & DMA_RDES0_OWN) == 0)
{
if ((Gmac->RxDesc->Status & DMA_RDES0_LAST_DESCRIPTOR) != 0)
{
/* increment segment count */
Gmac->DMARxFrameInfos.SegCount++;
/* Check if last segment is first segment: one segment contains the frame */
if (1U == Gmac->DMARxFrameInfos.SegCount)
{
(Gmac->DMARxFrameInfos).FSRxDesc = Gmac->RxDesc;
}
Gmac->DMARxFrameInfos.LSRxDesc = Gmac->RxDesc;
/* Get the Frame Length of the received packet: substruct 4 bytes of the CRC */
FrameLength = (((Gmac->RxDesc)->Status & DMA_RDES0_FRAME_LEN_MASK) >> 16U) - 4U;
Gmac->DMARxFrameInfos.length = FrameLength;
/* Get the address of the buffer start address */
Gmac->DMARxFrameInfos.buffer = ((Gmac->DMARxFrameInfos).FSRxDesc)->Buffer1Addr;
/* point to next descriptor */
Gmac->RxDesc = (FGmac_DmaDesc_t *)((Gmac->RxDesc)->Buffer2NextDescAddr);
return FST_SUCCESS;
}
/* Check if first segment */
else if ((Gmac->RxDesc->Status & DMA_RDES0_FIRST_DESCRIPTOR) == (u32)DMA_RDES0_FIRST_DESCRIPTOR)
{
(Gmac->DMARxFrameInfos).FSRxDesc = Gmac->RxDesc;
(Gmac->DMARxFrameInfos).LSRxDesc = NULL;
(Gmac->DMARxFrameInfos).SegCount = 1U;
/* Point to next descriptor */
Gmac->RxDesc = (FGmac_DmaDesc_t *)(Gmac->RxDesc->Buffer2NextDescAddr);
} /* Check if intermediate segment */
else
{
(Gmac->DMARxFrameInfos).SegCount++;
/* Point to next descriptor */
Gmac->RxDesc = (FGmac_DmaDesc_t *)(Gmac->RxDesc->Buffer2NextDescAddr);
}
}
return FST_FAILURE;
}

View File

@ -0,0 +1,20 @@
/*
 * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
 *
 * SPDX-License-Identifier: Apache-2.0.
 *
* @Date: 2021-04-07 09:53:07
* @LastEditTime: 2021-04-07 13:24:16
* @Description:  This files is for gmac descrption
*
* @Modify History:
* Ver   Who        Date         Changes
* ----- ------     --------    --------------------------------------
*/
#ifndef GMAC_DESC_H
#define GMAC_DESC_H
#include "ft_gmac.h"
#endif // !

View File

@ -0,0 +1,47 @@
/*
 * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
 *
 * SPDX-License-Identifier: Apache-2.0.
 *
* @Date: 2021-04-07 09:53:07
* @LastEditTime: 2021-04-07 13:24:30
* @Description:  This files is for gmac config
*
* @Modify History:
* Ver   Who        Date         Changes
* ----- ------     --------    --------------------------------------
*/
#include "ft_gmac.h"
#include "ft_parameters.h"
FGmac_Config_t Gmac_ConfigTable[FT_GMAC_INSTANCES_NUM] = {
{FT_GMAC0_ID,
FT_GMAC_COMMON_ADDR,
FT_GMAC0_BASEADDR,
GMAC0_ISRNUM,
GMAC0_ISRPRIORITY,
0,
5,
GMAC_AUTONEGOTIATION_ENABLE,
GMAC_SPEED_1000M,
GMAC_MODE_FULLDUPLEX,
GMAC_RXINTERRUPT_MODE,
GMAC_CHECKSUM_BY_SOFTWARE,
GMAC_MEDIA_INTERFACE_RGMII,
FT_GMAC0_DEFAULT_ADDR},
{FT_GMAC1_ID,
FT_GMAC_COMMON_ADDR,
FT_GMAC1_BASEADDR,
GMAC1_ISRNUM,
GMAC1_ISRPRIORITY,
0,
5,
GMAC_AUTONEGOTIATION_ENABLE,
GMAC_SPEED_1000M,
GMAC_MODE_FULLDUPLEX,
GMAC_RXINTERRUPT_MODE,
GMAC_CHECKSUM_BY_SOFTWARE,
GMAC_MEDIA_INTERFACE_RGMII,
{0}},
};

View File

@ -0,0 +1,566 @@
/*
 * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
 *
 * SPDX-License-Identifier: Apache-2.0.
 *
* @Date: 2021-04-07 09:53:07
* @LastEditTime: 2021-05-25 16:42:23
* @Description:  This files is for gmac register
*
* @Modify History:
* Ver   Who        Date         Changes
* ----- ------     --------    --------------------------------------
*/
#include "ft_gmac_hw.h"
#include "ft_types.h"
#include "ft_generic_timer.h"
#include "ft_assert.h"
#include "ft_status.h"
#include "ft_io.h"
#include "ft_debug.h"
#define PHY_CONFIG_DELAY_US 100
#define GMAC_HW_DEBUG_TAG "GMAC_HW"
#define GMAC_HW_DEBUG_I(format, ...) FT_DEBUG_PRINT_I(GMAC_HW_DEBUG_TAG, format, ##__VA_ARGS__)
#define GMAC_HW_DEBUG_E(format, ...) FT_DEBUG_PRINT_E(GMAC_HW_DEBUG_TAG, format, ##__VA_ARGS__)
#define GMAC_HW_DEBUG_W(format, ...) FT_DEBUG_PRINT_W(GMAC_HW_DEBUG_TAG, format, ##__VA_ARGS__)
s32 Gmac_WritePHYRegister(FGmac_Config_t *Config, u16 PHYReg, u32 RegValue)
{
u32 TmpReg;
u32 Wait_Counter = 0;
TmpReg = Ft_in32(Config->BaseAddress + GMAC_MII_ADDR_OFFSET);
TmpReg |= GMAC_MII_ADDR_CR(Config->clkMDC);
TmpReg |= GMAC_MII_ADDR_PA(Config->PhyAddr); /* Set the PHY device address */
TmpReg |= GMAC_MII_ADDR_GR(PHYReg); /* Set the PHY register address */
TmpReg |= GMAC_MII_ADDR_GW; /* Set the write mode */
TmpReg |= GMAC_MII_ADDR_GB; /* Set the MII Busy bit */
Ft_out32(Config->BaseAddress + GMAC_MII_DATA_OFFSET, RegValue);
Ft_out32(Config->BaseAddress + GMAC_MII_ADDR_OFFSET, TmpReg);
/* Check for the Busy flag */
while ((Ft_in32(Config->BaseAddress + GMAC_MII_ADDR_OFFSET) & GMAC_MII_ADDR_GB) == GMAC_MII_ADDR_GB)
{
if (10000000 <= ++Wait_Counter)
{
GMAC_HW_DEBUG_E("Gmac_WritePHYRegister FST_ERROR_COUNT_MAX \r\n");
return FST_ERROR_COUNT_MAX;
}
}
return FST_SUCCESS;
}
s32 FGmac_ReadPHYRegister(FGmac_Config_t *Config, u16 PHYReg, u32 *RegValue)
{
u32 TmpReg;
u32 Wait_Counter = 0;
TmpReg = 0;
TmpReg |= GMAC_MII_ADDR_CR(Config->clkMDC);
TmpReg |= GMAC_MII_ADDR_PA(Config->PhyAddr); /* Set the PHY device address */
TmpReg |= GMAC_MII_ADDR_GR(PHYReg); /* Set the PHY register address */
TmpReg &= ~GMAC_MII_ADDR_GW; /* Set the read mode */
TmpReg |= GMAC_MII_ADDR_GB; /* Set the MII Busy bit */
while ((Ft_in32(Config->BaseAddress + GMAC_MII_ADDR_OFFSET) & GMAC_MII_ADDR_GB) == GMAC_MII_ADDR_GB)
{
if (10000000 <= ++Wait_Counter)
{
GMAC_HW_DEBUG_E("wait GMAC_MII_ADDR_GB is error \r\n");
*RegValue = 0xffff;
return FST_ERROR_COUNT_MAX;
}
}
Ft_out32(Config->BaseAddress + GMAC_MII_ADDR_OFFSET, TmpReg);
while ((Ft_in32(Config->BaseAddress + GMAC_MII_ADDR_OFFSET) & GMAC_MII_ADDR_GB) == GMAC_MII_ADDR_GB)
{
if (10000000 <= ++Wait_Counter)
{
GMAC_HW_DEBUG_E("wait GMAC_MII_ADDR_GB 2 is error \r\n");
*RegValue = 0xffff;
return FST_ERROR_COUNT_MAX;
}
}
*RegValue = Ft_in32(Config->BaseAddress + GMAC_MII_DATA_OFFSET);
return FST_SUCCESS;
}
static s32 FGmac_PhyAddrGet(FGmac_Config_t *Config)
{
u32 i = 0;
u32 phyId1;
u32 phyId2;
u8 flag = 0;
for (i = 0; i < 32; i++)
{
Config->PhyAddr = i;
FGmac_ReadPHYRegister(Config, PHY_ID1_REG_OFFSET, &phyId1);
FGmac_ReadPHYRegister(Config, PHY_ID2_REG_OFFSET, &phyId2);
if ((phyId2 & 0xffff) != 0xffff)
{
if ((0 == i) && (0x1c == phyId1) && ((phyId2 >> 10) == 0x32))
{
continue;
}
flag = 1;
break;
}
}
return (flag == 1) ? FST_SUCCESS : FST_FAILURE;
}
static void FGmac_MACAddressConfig(FGmac_Config_t *Config, u32 MacAddr, u8 *Addr)
{
u32 tmpreg;
/* Calculate the selected MAC address high register */
tmpreg = ((u32)Addr[5] << 8) | (u32)Addr[4];
/* Load the selected MAC address high register */
Ft_out32(Config->BaseAddress + GMAC_MAC_ADDR0_UPPER16BIT_OFFSET + MacAddr, tmpreg);
/* Calculate the selected MAC address low register */
tmpreg = ((u32)Addr[3] << 24) | ((u32)Addr[2] << 16) | ((u32)Addr[1] << 8) | Addr[0];
/* Load the selected MAC address low register */
Ft_out32(Config->BaseAddress + GMAC_MAC_ADDR0_LOWER16BIT_OFFSET + MacAddr, tmpreg);
}
static void FGmac_MACDMAInit(FGmac_Config_t *Config)
{
u32 RegValue = 0;
Ft_assertVoid(FGmac_PhyAddrGet(Config) == FST_SUCCESS);
RegValue = Ft_in32(Config->BaseAddress + GMAC_CONTROL_OFFSET);
/* MACCR Configuration **************************************/
/* Set the WD bit according to ETH Watchdog value */
/* Set the JD: bit according to ETH Jabber value */
/* Set the IFG bit according to ETH InterFrameGap value */
/* Set the DCRS bit according to ETH CarrierSense value */
/* Set the FES bit according to ETH Speed value */
/* Set the DO bit according to ETH ReceiveOwn value */
/* Set the LM bit according to ETH LoopbackMode value */
/* Set the DM bit according to ETH Mode value */
/* Set the IPCO bit according to ETH ChecksumOffload value */
/* Set the DR bit according to ETH RetryTransmission value */
/* Set the ACS bit according to ETH AutomaticPadCRCStrip value */
/* Set the BL bit according to ETH BackOffLimit value */
/* Set the DC bit according to ETH DeferralCheck value */
RegValue &= ~GMAC_CONTROL_WD;
RegValue &= ~GMAC_CONTROL_JD;
RegValue |= GMAC_CONTROL_IFG(0);
RegValue &= ~GMAC_CONTROL_DCRS;
RegValue &= ~GMAC_CONTROL_DO;
RegValue &= ~GMAC_CONTROL_LM;
if (Config->ChecksumMode)
{
RegValue |= GMAC_CONTROL_IPC;
}
else
{
RegValue &= ~GMAC_CONTROL_IPC;
}
RegValue |= GMAC_CONTROL_DR;
RegValue &= ~GMAC_CONTROL_ACS;
RegValue |= GMAC_CONTROL_BL(0);
RegValue &= ~GMAC_CONTROL_DC;
if (Config->DuplexMode == GMAC_MODE_FULLDUPLEX)
{
RegValue |= GMAC_CONTROL_DM;
}
else
{
RegValue &= ~GMAC_CONTROL_DM;
}
RegValue &= ~GMAC_CONTROL_FES;
Ft_out32(Config->BaseAddress + GMAC_CONTROL_OFFSET, RegValue);
Ft_GenericTimer_UsDelay(PHY_CONFIG_DELAY_US);
/*----------------------- GMAC MACFFR Configuration --------------------*/
/* Set the RA bit according to ETH ReceiveAll value */
/* Set the SAF and SAIF bits according to ETH SourceAddrFilter value */
/* Set the PCF bit according to ETH PassControlFrames value */
/* Set the DBF bit according to ETH BroadcastFramesReception value */
/* Set the DAIF bit according to ETH DestinationAddrFilter value */
/* Set the PR bit according to ETH PromiscuousMode value */
/* Set the PM, HMC and HPF bits according to ETH MulticastFramesFilter value */
/* Set the HUC and HPF bits according to ETH UnicastFramesFilter value */
/* Write to MACFFR */
RegValue = Ft_in32(Config->BaseAddress + GMAC_FRAME_FILTER_OFFSET);
RegValue |= GMAC_FRAME_FILTER_RA;
RegValue |= GMAC_FRAME_FILTER_PCF(2);
RegValue &= ~GMAC_FRAME_FILTER_PM;
RegValue &= ~GMAC_FRAME_FILTER_DBF;
RegValue &= ~GMAC_FRAME_FILTER_DAIF;
RegValue &= ~GMAC_FRAME_FILTER_PR;
Ft_out32(Config->BaseAddress + GMAC_FRAME_FILTER_OFFSET, RegValue);
Ft_GenericTimer_UsDelay(PHY_CONFIG_DELAY_US);
/*--------------- MACHTHR and MACHTLR Configuration --------------*/
Ft_out32(Config->BaseAddress + GMAC_HASH_HIGH_OFFSET, 0);
Ft_GenericTimer_UsDelay(PHY_CONFIG_DELAY_US);
Ft_out32(Config->BaseAddress + GMAC_HASH_LOW_OFFSET, 0);
Ft_GenericTimer_UsDelay(PHY_CONFIG_DELAY_US);
/*----------------------- MACFCR Configuration -------------------*/
/* Set the PT bit according to ETH PauseTime value */
/* Set the DZPQ bit according to ETH ZeroQuantaPause value */
/* Set the PLT bit according to ETH PauseLowThreshold value */
/* Set the UP bit according to ETH UnicastPauseFrameDetect value */
/* Set the RFE bit according to ETH ReceiveFlowControl value */
/* Set the TFE bit according to ETH TransmitFlowControl value */
RegValue = Ft_in32(Config->BaseAddress + GMAC_FLOW_CTRL_OFFSET);
RegValue |= GMAC_FLOW_DZPQ;
RegValue |= GMAC_FLOW_PLT(0);
RegValue &= ~GMAC_FLOW_RFE;
RegValue &= ~GMAC_FLOW_TFE;
Ft_out32(Config->BaseAddress + GMAC_FLOW_CTRL_OFFSET, RegValue);
Ft_GenericTimer_UsDelay(PHY_CONFIG_DELAY_US);
/*----------------------- MACVLANTR Configuration ----------------*/
/* Set the ETV bit according to ETH VLANTagComparison value */
/* Set the VL bit according to ETH VLANTagIdentifier value */
RegValue = GMAC_VLAN_TAG_VL(0);
RegValue &= ~GMAC_VLAN_TAG_ETV;
Ft_out32(Config->BaseAddress + GMAC_VLAN_TAG_OFFSET, RegValue);
Ft_GenericTimer_UsDelay(PHY_CONFIG_DELAY_US);
/* DMA default initialization ************************************/
/* Set the DT bit according to ETH DropTCPIPChecksumErrorFrame value */
/* Set the RSF bit according to ETH ReceiveStoreForward value */
/* Set the DFF bit according to ETH FlushReceivedFrame value */
/* Set the TSF bit according to ETH TransmitStoreForward value */
/* Set the TTC bit according to ETH TransmitThresholdControl value */
/* Set the FEF bit according to ETH ForwardErrorFrames value */
/* Set the FUF bit according to ETH ForwardUndersizedGoodFrames value */
/* Set the RTC bit according to ETH ReceiveThresholdControl value */
/* Set the OSF bit according to ETH SecondFrameOperate value */
RegValue = Ft_in32(Config->BaseAddress + DMA_OP_OFFSET);
RegValue &= DMA_OP_CLEAR_MASK;
RegValue &= ~DMA_OP_DT;
RegValue |= DMA_OP_RSF;
RegValue &= ~DMA_OP_DFF;
RegValue |= DMA_OP_TSF;
RegValue |= DMA_OP_TTC(7);
RegValue |= DMA_OP_OSF;
Ft_out32(Config->BaseAddress + DMA_OP_OFFSET, RegValue);
Ft_GenericTimer_UsDelay(PHY_CONFIG_DELAY_US);
/* DMABMR Configuration ------------------*/
/* Set the AAL bit according to ETH AddressAlignedBeats value */
/* Set the FB bit according to ETH FixedBurst value */
/* Set the RPBL and 4*PBL bits according to ETH RxDMABurstLength value */
/* Set the PBL and 4*PBL bits according to ETH TxDMABurstLength value */
/* Set the Enhanced DMA descriptors bit according to ETH EnhancedDescriptorFormat value*/
/* Set the DSL bit according to ETH DesciptorSkipLength value */
/* Set the PR and DA bits according to ETH DMAArbitration value */
RegValue = Ft_in32(Config->BaseAddress + DMA_BUS_MODE_OFFSET);
RegValue |= DMA_BUS_AAL;
RegValue |= DMA_BUS_FB;
RegValue |= DMA_BUS_RPBL(32);
RegValue |= DMA_BUS_PBL(32);
RegValue |= DMA_BUS_ATDS;
RegValue |= DMA_BUS_PR(0);
RegValue |= DMA_BUS_USP;
Ft_out32(Config->BaseAddress + DMA_BUS_MODE_OFFSET, RegValue);
Ft_GenericTimer_UsDelay(PHY_CONFIG_DELAY_US);
Ft_out32(Config->BaseAddress + DMA_AXI_BUS_MOD_OFFSET, 0x0000000e);
FGmac_MACAddressConfig(Config, 0, Config->MacAddr);
}
s32 FGmac_InitializeHw(FGmac_Config_t *Config)
{
u32 Wait_Counter = 0;
u32 RegValue;
s32 ret = FST_SUCCESS;
/*Gmac Software reset */
Ft_out32(Config->BaseAddress + DMA_BUS_MODE_OFFSET, DMA_BUS_SWR);
while ((Ft_in32(Config->BaseAddress + DMA_BUS_MODE_OFFSET) & DMA_BUS_SWR) == DMA_BUS_SWR)
{
if (++Wait_Counter > 30)
{
GMAC_HW_DEBUG_E("DMA_BUS_MODE_OFFSET wait is too long ,Addr %x \r\n", Config->BaseAddress);
return FST_ERROR_COUNT_MAX;
}
Ft_GenericTimer_UsDelay(PHY_CONFIG_DELAY_US);
}
Wait_Counter = 0;
Ft_out32(Config->BaseAddress + DMA_BUS_MODE_OFFSET, DMA_BUS_INIT);
Ft_out32(Config->BaseAddress + DMA_OP_OFFSET, Ft_in32(Config->BaseAddress + DMA_OP_OFFSET) | DMA_OP_FTF);
while ((Ft_in32(Config->BaseAddress + DMA_OP_OFFSET) & DMA_OP_FTF) == DMA_OP_FTF)
{
if (++Wait_Counter > 30)
{
GMAC_HW_DEBUG_E("DMA_OP_OFFSET wait is too long \r\n");
return FST_ERROR_COUNT_MAX;
}
Ft_GenericTimer_UsDelay(PHY_CONFIG_DELAY_US);
}
Wait_Counter = 0;
/* GMAC Init */
Ft_out32(Config->BaseAddress + GMAC_CONTROL_OFFSET, GMAC_CONTROL_INIT);
/* disable flow control */
Ft_out32(Config->BaseAddress + GMAC_FLOW_CTRL_OFFSET, 0);
Ft_out32(Config->BaseAddress + DMA_STATUS_OFFSET, DMA_STATUS_INIT);
Ft_out32(Config->BaseAddress + DMA_INTR_ENA_OFFSET, 0);
/* get Phy addr */
Ft_assertNonvoid(FGmac_PhyAddrGet(Config) == FST_SUCCESS);
/*-------------------------------- MAC Initialization ----------------------*/
/*-------------------- PHY initialization and configuration ----------------*/
/* Put the PHY in reset mode */
if (Gmac_WritePHYRegister(Config, PHY_BCR_OFFSET, PHY_RESET) != FST_SUCCESS)
{
GMAC_HW_DEBUG_E("PHY_BCR_OFFSET is error \r\n");
return FST_FAILURE;
}
do
{
FGmac_ReadPHYRegister(Config, PHY_BCR_OFFSET, &RegValue);
Ft_GenericTimer_UsDelay(PHY_CONFIG_DELAY_US);
if (++Wait_Counter > 30)
{
GMAC_HW_DEBUG_E("PHY_BCR_OFFSET wait is too long \r\n");
ret = FST_ERROR_COUNT_MAX;
goto gmac_init;
}
} while ((RegValue & PHY_RESET) == PHY_RESET);
Wait_Counter = 0;
if (Config->AutoNegotiation == GMAC_AUTONEGOTIATION_ENABLE)
{
do
{
FGmac_ReadPHYRegister(Config, PHY_BSR_OFFSET, &RegValue);
if (++Wait_Counter > 30)
{
GMAC_HW_DEBUG_E("PHY_BSR_OFFSET 1 wait is too long \r\n");
ret = FST_ERROR_COUNT_MAX;
goto gmac_init;
}
Ft_GenericTimer_UsDelay(PHY_CONFIG_DELAY_US);
} while ((RegValue & PHY_LINKED_STATUS) != PHY_LINKED_STATUS);
Wait_Counter = 0;
if (Gmac_WritePHYRegister(Config, PHY_BCR_OFFSET, PHY_AUTONEGOTIATION | PHY_RESTART_AUTONEGOTIATION) != FST_SUCCESS)
{
GMAC_HW_DEBUG_E("PHY_BCR_OFFSET 2 is error \r\n");
ret = FST_FAILURE;
goto gmac_init;
}
do
{
FGmac_ReadPHYRegister(Config, PHY_BSR_OFFSET, &RegValue);
if (++Wait_Counter > 30)
{
GMAC_HW_DEBUG_E("PHY_BSR_OFFSET 2 wait is too long \r\n");
ret = FST_ERROR_COUNT_MAX;
goto gmac_init;
}
} while ((RegValue & PHY_AUTONEGO_COMPLETE) != PHY_AUTONEGO_COMPLETE);
if (FGmac_ReadPHYRegister(Config, PHY_SPECIFIC_STATUS_OFFSET, &RegValue) != FST_SUCCESS)
{
GMAC_HW_DEBUG_E("PHY_SPECIFIC_STATUS_OFFSET is error \r\n");
ret = FST_FAILURE;
goto gmac_init;
}
/* Configure the MAC with the Duplex Mode fixed by the auto-negotiation process */
if ((RegValue & PHY_SPECIFIC_STATUS_DUPLEX) != PHY_SPECIFIC_STATUS_DUPLEX)
{
/* Set Ethernet duplex mode to Full-duplex following the auto-negotiation */
Config->DuplexMode = GMAC_MODE_HALFDUPLEX;
}
else
{
/* Set Ethernet duplex mode to Half-duplex following the auto-negotiation */
Config->DuplexMode = GMAC_MODE_FULLDUPLEX;
}
}
else
{
RegValue = 0;
if (Config->DuplexMode == GMAC_MODE_FULLDUPLEX)
{
if (Config->Speed == GMAC_SPEED_1000M)
{
RegValue = PHY_FULLDUPLEX_1000M;
}
else if (Config->Speed == GMAC_SPEED_100M)
{
RegValue = PHY_FULLDUPLEX_100M;
}
else if (Config->Speed == GMAC_SPEED_10M)
{
RegValue = PHY_FULLDUPLEX_10M;
}
}
else
{
if (Config->Speed == GMAC_SPEED_1000M)
{
RegValue = PHY_HALFDUPLEX_1000M;
}
else if (Config->Speed == GMAC_SPEED_100M)
{
RegValue = PHY_HALFDUPLEX_100M;
}
else if (Config->Speed == GMAC_SPEED_10M)
{
RegValue = PHY_HALFDUPLEX_10M;
}
}
/* AutoNegotiation Disable */
if (Gmac_WritePHYRegister(Config, PHY_BCR_OFFSET, RegValue) != FST_SUCCESS)
{
GMAC_HW_DEBUG_E("PHY_BCR_OFFSET 3 is error \r\n");
ret = FST_FAILURE;
goto gmac_init;
}
}
Ft_GenericTimer_UsDelay(PHY_CONFIG_DELAY_US);
gmac_init:
FGmac_MACDMAInit(Config);
return ret;
}
void FGmac_TransmissionEnable(FGmac_Config_t *Config)
{
u32 RegValue;
RegValue = Ft_in32(Config->BaseAddress + GMAC_CONTROL_OFFSET);
RegValue |= GMAC_CONTROL_TE;
Ft_out32(Config->BaseAddress + GMAC_CONTROL_OFFSET, RegValue);
}
void FGmac_TransmissionDisable(FGmac_Config_t *Config)
{
u32 RegValue;
RegValue = Ft_in32(Config->BaseAddress + GMAC_CONTROL_OFFSET);
RegValue &= ~GMAC_CONTROL_TE;
Ft_out32(Config->BaseAddress + GMAC_CONTROL_OFFSET, RegValue);
}
void FGmac_ReceptionEnable(FGmac_Config_t *Config)
{
u32 RegValue;
RegValue = Ft_in32(Config->BaseAddress + GMAC_CONTROL_OFFSET);
RegValue |= GMAC_CONTROL_RE;
Ft_out32(Config->BaseAddress + GMAC_CONTROL_OFFSET, RegValue);
}
void FGmac_ReceptionDisable(FGmac_Config_t *Config)
{
u32 RegValue;
RegValue = Ft_in32(Config->BaseAddress + GMAC_CONTROL_OFFSET);
RegValue &= ~GMAC_CONTROL_RE;
Ft_out32(Config->BaseAddress + GMAC_CONTROL_OFFSET, RegValue);
}
void FGmac_FlushTransmitFIFO(FGmac_Config_t *Config)
{
u32 RegValue;
RegValue = Ft_in32(Config->BaseAddress + DMA_OP_OFFSET);
RegValue |= DMA_OP_FTF;
Ft_out32(Config->BaseAddress + DMA_OP_OFFSET, RegValue);
}
void FGmac_DMATransmissionEnable(FGmac_Config_t *Config)
{
u32 RegValue;
RegValue = Ft_in32(Config->BaseAddress + DMA_OP_OFFSET);
RegValue |= DMA_OP_ST;
Ft_out32(Config->BaseAddress + DMA_OP_OFFSET, RegValue);
}
/**
* @name: FGmac_DMATransmissionDisable
* @msg: Disable the DMA transmission
* @param {FGmac_Config_t} *Config
* @return {*}
*/
void FGmac_DMATransmissionDisable(FGmac_Config_t *Config)
{
u32 RegValue;
RegValue = Ft_in32(Config->BaseAddress + DMA_OP_OFFSET);
RegValue &= ~DMA_OP_ST;
Ft_out32(Config->BaseAddress + DMA_OP_OFFSET, RegValue);
}
/**
* @name: FGmac_DMAReceptionEnable
* @msg: Enable the DMA reception
* @param {FGmac_Config_t} *Config
* @return {*}
*/
void FGmac_DMAReceptionEnable(FGmac_Config_t *Config)
{
u32 RegValue;
RegValue = Ft_in32(Config->BaseAddress + DMA_OP_OFFSET);
RegValue |= DMA_OP_SR;
Ft_out32(Config->BaseAddress + DMA_OP_OFFSET, RegValue);
}
void FGmac_DMAReceptionDisable(FGmac_Config_t *Config)
{
u32 RegValue;
RegValue = Ft_in32(Config->BaseAddress + DMA_OP_OFFSET);
RegValue &= ~DMA_OP_SR;
Ft_out32(Config->BaseAddress + DMA_OP_OFFSET, RegValue);
}
void FGmac_DMAReceptionTransmissionEnable(FGmac_Config_t *Config)
{
u32 RegValue;
RegValue = Ft_in32(Config->BaseAddress + DMA_OP_OFFSET);
RegValue |= (DMA_OP_SR | DMA_OP_ST);
Ft_out32(Config->BaseAddress + DMA_OP_OFFSET, RegValue);
}
void FGmac_DMAReceptionTransmissionDisable(FGmac_Config_t *Config)
{
u32 RegValue;
RegValue = Ft_in32(Config->BaseAddress + DMA_OP_OFFSET);
RegValue &= ~(DMA_OP_SR | DMA_OP_ST);
Ft_out32(Config->BaseAddress + DMA_OP_OFFSET, RegValue);
}
void FGmac_ReceptionTransmissionEnable(FGmac_Config_t *Config)
{
u32 RegValue;
RegValue = Ft_in32(Config->BaseAddress + GMAC_CONTROL_OFFSET);
RegValue |= (GMAC_CONTROL_RE | GMAC_CONTROL_TE);
Ft_out32(Config->BaseAddress + GMAC_CONTROL_OFFSET, RegValue);
}
void FGmac_ReceptionTransmissionDisable(FGmac_Config_t *Config)
{
u32 RegValue;
RegValue = Ft_in32(Config->BaseAddress + GMAC_CONTROL_OFFSET);
RegValue &= ~(GMAC_CONTROL_RE | GMAC_CONTROL_TE);
Ft_out32(Config->BaseAddress + GMAC_CONTROL_OFFSET, RegValue);
}

View File

@ -0,0 +1,577 @@
/*
 * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
 *
 * SPDX-License-Identifier: Apache-2.0.
 *
* @Date: 2021-04-07 09:53:07
* @LastEditTime: 2021-04-07 13:25:10
* @Description:  This files is for gmac register
*
* @Modify History:
* Ver   Who        Date         Changes
* ----- ------     --------    --------------------------------------
*/
#ifndef GMAC_HW_H
#define GMAC_HW_H
#include "ft_types.h"
#include "ft_gmac.h"
/* Register Offset */
#define GMAC_CONTROL_OFFSET 0x00000000U /* Configuration */
#define GMAC_FRAME_FILTER_OFFSET 0x00000004U /* Frame Filter */
#define GMAC_HASH_HIGH_OFFSET 0x00000008U /* Multicast Hash Table High */
#define GMAC_HASH_LOW_OFFSET 0x0000000cU /* Multicast Hash Table Low */
#define GMAC_MII_ADDR_OFFSET 0x00000010U /* MII Address */
#define GMAC_MII_DATA_OFFSET 0x00000014U /* MII Data */
#define GMAC_FLOW_CTRL_OFFSET 0x00000018U /* Flow Control */
#define GMAC_VLAN_TAG_OFFSET 0x0000001cU /* VLAN Tag */
#define GMAC_VERSION_OFFSET 0x00000020U /* GMAC CORE Version */
#define GMAC_INTERNAL_MODULE_STATUS_OFFSET 0x00000024U /* 给出各种内部块的状态以进行调试。 */
#define GMAC_LPI_CONTROL_STATUS_OFFSET 0x00000030U /* 控制低功耗空闲LPI操作并提供内核的 LPI 状态。 */
#define GMAC_LPI_TIMER_CONTROL_OFFSET 0x00000034U /* 控制 LPI 状态中的超时值。 */
#define GMAC_ISR_STATUS_OFFSET 0x00000038U /* 中断状态。 */
#define GMAC_ISR_MASK_OFFSET 0x0000003CU /* 生成中断的掩码 */
#define GMAC_MAC_ADDR0_UPPER16BIT_OFFSET 0x00000040U /* 第一个 MAC 地址的高 16 位。 */
#define GMAC_MAC_ADDR0_LOWER16BIT_OFFSET 0x00000044U /* 第一个 MAC 地址的低 32 位。。 */
#define GMAC_MAC_ADDR1_UPPER16BIT_OFFSET 0x00000048U /* 第二个 MAC 地址的高 16 位。 */
#define GMAC_MAC_ADDR1_LOWER16BIT_OFFSET 0x0000004CU /* 第二个 MAC 地址的低 32 位。。 */
#define GMAC_MAC_MAC_PHY_STATUS 0x000000D8U /* MAC PHY 状态 */
#define DMA_BUS_MODE_OFFSET 0x00001000U /* Bus Mode */
#define DMA_XMT_POLL_DEMAND_OFFSET 0x00001004U /* Transmit Poll Demand */
#define DMA_RCV_POLL_DEMAND_OFFSET 0x00001008U /* Received Poll Demand */
#define DMA_RCV_BASE_ADDR_OFFSET 0x0000100cU /* Receive List Base */
#define DMA_TX_BASE_ADDR_OFFSET 0x00001010U /* Transmit List Base */
#define DMA_STATUS_OFFSET 0x00001014U /* Status Register */
#define DMA_OP_OFFSET 0x00001018U /* Ctrl (Operational Mode) */
#define DMA_INTR_ENA_OFFSET 0x0000101cU /* Interrupt Enable */
#define DMA_MISSED_FRAME_CTR_OFFSET 0x00001020U /* Missed Frame Counter */
#define DMA_RX_WATCHDOG_OFFSET 0x1024U /* Receive Interrupt Watchdog */
#define DMA_AXI_BUS_MOD_OFFSET 0x1028U /* 控制 AXI 主行为 */
#define DMA_AXI_BUS_STATUS_OFFSET 0x102CU /* 控制 AXI 状态 */
/* MMC control */
#define MMC_CNTRL 0x0100U /* MMC Control */
#define MMC_RX_INTR 0x0104U /* MMC RX Interrupt */
#define MMC_TX_INTR 0x0108U /* MMC TX Interrupt */
#define MMC_RX_INTR_MASK 0x010cU /* MMC Interrupt Mask */
#define MMC_TX_INTR_MASK 0x0110U /* MMC Interrupt Mask */
#define MMC_RX_IPC_INTR_MASK 0x0200U
#define MMC_RX_IPC_INTR 0x0208U
/** MAC 配置寄存器 **/
#define GMAC_CONTROL_2K 0x08000000U /* IEEE 802.3as 2K packets */
#define GMAC_CONTROL_CST 0x2000000U
#define GMAC_CONTROL_TC 0x01000000U /* Transmit Conf. in RGMII/SGMII */
#define GMAC_CONTROL_WD 0x00800000U /* Disable Watchdog on receive */
#define GMAC_CONTROL_JD 0x00400000U /* Jabber disable */
#define GMAC_CONTROL_BE 0x00200000U /* Frame Burst Enable */
#define GMAC_CONTROL_JE 0x00100000U /* Jumbo frame */
#define GMAC_CONTROL_IFG(x) ((x & 7) << 17) /* 帧内间隔 ,000 96bit times 001 88bit times 010 80bit times … 111 40bit times*/
#define GMAC_CONTROL_DCRS 0x00010000U /* Disable carrier sense */
#define GMAC_CONTROL_PS 0x00008000U /* Port Select 0:GMII 1:MII */
#define GMAC_CONTROL_FES 0x00004000U /* Speed 0:10 1:100 */
#define GMAC_CONTROL_DO 0x00002000U /* Disable Rx Own */
#define GMAC_CONTROL_LM 0x00001000U /* Loop-back mode */
#define GMAC_CONTROL_DM 0x00000800U /* Duplex Mode . 1 is Duplex */
#define GMAC_CONTROL_IPC 0x00000400U /* Checksum Offload */
#define GMAC_CONTROL_DR 0x00000200U /* Disable Retry */
#define GMAC_CONTROL_LUD 0x00000100U /* Link up/down */
#define GMAC_CONTROL_ACS 0x00000080U /* Auto Pad/FCS Stripping */
#define GMAC_CONTROL_BL(x) ((x & 3) << 5)
#define GMAC_CONTROL_DC 0x00000010U /* Deferral Check */
#define GMAC_CONTROL_TE 0x00000008U /* Transmitter Enable */
#define GMAC_CONTROL_RE 0x00000004U /* Receiver Enable */
#define GMAC_CONTROL_INIT (GMAC_CONTROL_DO | GMAC_CONTROL_JD | GMAC_CONTROL_ACS | GMAC_CONTROL_IPC | GMAC_CONTROL_BE | GMAC_CONTROL_DM | GMAC_CONTROL_WD | GMAC_CONTROL_CST)
/** Frame Filter **/
#define GMAC_FRAME_FILTER_PR 0x00000001U
#define GMAC_FRAME_FILTER_HUC 0x00000002U
#define GMAC_FRAME_FILTER_HMC 0x00000004U
#define GMAC_FRAME_FILTER_DAIF 0x00000008U
#define GMAC_FRAME_FILTER_PM 0x00000010U
#define GMAC_FRAME_FILTER_DBF 0x00000020U
#define GMAC_FRAME_FILTER_PCF(x) ((x & 3) << 6)
#define GMAC_FRAME_FILTER_SAIF 0x00000100U
#define GMAC_FRAME_FILTER_SAF 0x00000200U
#define GMAC_FRAME_FILTER_HPF 0x00000400U
#define GMAC_FRAME_FILTER_RA 0x80000000U
/** 哈希表高位寄存器 **/
#define GMAC_HASH_HIGH_HTH 0xffffffffUL /* 该字段包含 Hash 表的高 32 位。 */
/** 哈希表低位寄存器 **/
#define GMAC_HASH_LOW_HTH 0xffffffffUL /* 该字段包含 Hash 表的低 32 位。 */
/** GMII 地址寄存器 **/
#define GMAC_MII_ADDR_GB 0x00000001
#define GMAC_MII_ADDR_GW 0x00000002
#define GMAC_MII_ADDR_CR(x) ((x & 0xf) << 2)
#define GMAC_MII_ADDR_GR(x) ((x & 0x1f) << 6)
#define GMAC_MII_ADDR_PA(x) ((x & 0x1f) << 11)
/** GMII 数据寄存器 **/
#define GMAC_MII_DATA_GD 0x0000ffffU
/** 流控寄存器 **/
#define GMAC_FLOW_FCB 0x00000001U
#define GMAC_FLOW_BPA GMAC_FLOW_FCB
#define GMAC_FLOW_TFE 0x00000002U
#define GMAC_FLOW_RFE 0x00000004U
#define GMAC_FLOW_UP 0x00000008U
#define GMAC_FLOW_PLT(x) ((x & 3) << 3)
#define GMAC_FLOW_DZPQ 0x00000080U
#define GMAC_FLOW_PT 0xffff0000U
/** VLAN 标记寄存器 **/
// #define GMAC_VLAN_TAG_VL 0x0000ffffU
#define GMAC_VLAN_TAG_VL(x) (x & 0xffffU)
#define GMAC_VLAN_TAG_ETV 0x00010000U
/** 版本寄存器 **/
#define GMAC_VERSION_UDV 0x00FF0000U /* 用户定义版本号 */
#define GMAC_VERSION_SDV 0x000000ffU /* 硬件定议版本号 */
/** LPI 控制和状态寄存器 **/
#define GMAC_LPI_CONTROL_STATUS_TLPIEN 0x00000001U
#define GMAC_LPI_CONTROL_STATUS_TLPIEX 0x00000002U
#define GMAC_LPI_CONTROL_STATUS_RLPIEN 0x00000004U
#define GMAC_LPI_CONTROL_STATUS_RLPIEX 0x00000008U
#define GMAC_LPI_CONTROL_STATUS_TLPIST 0x00000100U
#define GMAC_LPI_CONTROL_STATUS_RLPIST 0x00000200U
#define GMAC_LPI_CONTROL_STATUS_LPIEN 0x00010000U
#define GMAC_LPI_CONTROL_STATUS_PLS 0x00020000U
#define GMAC_LPI_CONTROL_STATUS_PLSEN 0x00040000U
#define GMAC_LPI_CONTROL_STATUS_LPITXA 0x00080000U
/** LPI 定时器控制寄存器 **/
#define GMAC_LPI_TIMER_TWT 0x0000ffffU
#define GMAC_LPI_TIMER_LIT 0x3FF0000U
/** 中断状态寄存器 **/
#define GMAC_ISR_STATUS_RSIS 0x00000001U
#define GMAC_ISR_STATUS_PCSLSC 0x00000002U
#define GMAC_ISR_STATUS_PCSANC 0x00000004U
#define GMAC_ISR_STATUS_PMTIS 0x00000008U
#define GMAC_ISR_STATUS_MMCIS 0x00000010U
#define GMAC_ISR_STATUS_MMCRIS 0x00000020U
#define GMAC_ISR_STATUS_MMCTIS 0x00000040U
#define GMAC_ISR_STATUS_MMCRCOIS 0x00000080U
#define GMAC_ISR_STATUS_TIS 0x00000200U
#define GMAC_ISR_STATUS_LPIIS 0x00000400U
/** 中断屏蔽寄存器 **/
#define GMAC_ISR_MASK_RSIM 0x00000001U /* RGMII/SMII 中断屏蔽 */
#define GMAC_ISR_MASK_PCSLSIM 0x00000002U
#define GMAC_ISR_MASK_PCSANCIM 0x00000004U
#define GMAC_ISR_MASK_PMTIM 0x00000008U
#define GMAC_ISR_MASK_TIM 0x00000020U
#define GMAC_ISR_MASK_LPIIM 0x00000040U
/** MAC 地址 0 高寄存器 **/
#define GMAC_MAC_ADDR0_UPPER16BIT_A 0x0000ffffU
/** MAC 地址 0 低寄存器 **/
#define GMAC_MAC_ADDR0_LOWERER16BIT_A 0xffffffffU
/** MAC 地址 1 高寄存器 **/
#define GMAC_MAC_ADDR1_UPPER16BIT_A 0x0000ffffU
#define GMAC_MAC_ADDR1_UPPER16BIT_MBC 0x3f000000U
#define GMAC_MAC_ADDR1_UPPER16BIT_SA 0x40000000U
#define GMAC_MAC_ADDR1_UPPER16BIT_AE 0x80000000U
/** MAC 地址 1 低寄存器 **/
#define GMAC_MAC_ADDR1_LOWER16BIT_A 0xffffffffU
/* GMAC DMA 寄存器 */
/** 总线模式寄存器 **/
#define DMA_BUS_PRWG 0x030000000U
#define DMA_BUS_TXPR 0x08000000U
#define DMA_BUS_MB 0x04000000U
#define DMA_BUS_AAL 0x02000000U
#define DMA_BUS_8xPBL 0x01000000U
#define DMA_BUS_USP 0x00800000U
#define DMA_BUS_RPBL(x) ((x & 0x3f) << 17)
#define DMA_BUS_FB 0x00010000U /* Fixed Burst */
#define DMA_BUS_PR(x) ((x & 0x3) << 14) /* 00: 1:1 ,01: 2:1 ,10: 3:1 ,11: 4:1 */
#define DMA_BUS_PBL(x) ((x & 0x3f) << 8)
#define DMA_BUS_ATDS 0x00000080U
#define DMA_BUS_DSL 0x0000007CU /* Descriptor Skip Length */
#define DMA_BUS_DA 0x00000002U /* DMA Arbitration Scheme,Rx High Pro */
#define DMA_BUS_SWR 0x00000001U /* Software Reset */
#define DMA_BUS_INIT (DMA_BUS_FB | DMA_BUS_PBL(16) | DMA_BUS_RPBL(16))
/** 发送轮询请求寄存器 **/
#define DMA_XMT_POLL_DEMAND_TPD 0xffffffffU
/** 发送轮询请求寄存器 **/
#define DMA_RCV_POLL_DEMAND_RPD 0xffffffffU
/** 接收描述符列表地址寄存器 **/
#define DMA_RCV_BASE_ADDR_START_REC_LIST 0xfffffff0U
/** 发送描述符列表地址寄存器 **/
#define DMA_TX_BASE_ADDR_START_TRA_LIST 0xfffffff0U
/**
* @brief Bit definition of TDES0 register: DMA Tx descriptor status register
*/
#define BIT(bitnum) (1 << (bitnum % 32))
#define GENMASK(h, l) \
(((~0UL) - (1UL << (l)) + 1) & (~0UL >> (32 - 1 - (h))))
#define DMA_TDES0_DEFERRED BIT(0)
#define DMA_TDES0_UNDERFLOW_ERROR BIT(1)
#define DMA_TDES0_EXCESSIVE_DEFERRAL BIT(2)
#define DMA_TDES0_COLLISION_COUNT_MASK GENMASK(6, 3)
#define DMA_TDES0_VLAN_FRAME BIT(7)
#define DMA_TDES0_EXCESSIVE_COLLISIONS BIT(8)
#define DMA_TDES0_LATE_COLLISION BIT(9)
#define DMA_TDES0_NO_CARRIER BIT(10)
#define DMA_TDES0_LOSS_CARRIER BIT(11)
#define DMA_TDES0_PAYLOAD_ERROR BIT(12)
#define DMA_TDES0_FRAME_FLUSHED BIT(13)
#define DMA_TDES0_JABBER_TIMEOUT BIT(14)
#define DMA_TDES0_ERROR_SUMMARY BIT(15)
#define DMA_TDES0_IP_HEADER_ERROR BIT(16)
#define DMA_TDES0_TIME_STAMP_STATUS BIT(17)
#define DMA_TDES0_OWN ((u32)BIT(31)) /* silence sparse */
/* TDES1 */
#define DMA_TDES1_BUFFER1_SIZE_MASK GENMASK(10, 0)
#define DMA_TDES1_BUFFER2_SIZE_MASK GENMASK(21, 11)
#define DMA_TDES1_BUFFER2_SIZE_SHIFT 11
#define DMA_TDES1_TIME_STAMP_ENABLE BIT(22)
#define DMA_TDES1_DISABLE_PADDING BIT(23)
#define DMA_TDES1_SECOND_ADDRESS_CHAINED BIT(24)
#define DMA_TDES1_END_RING BIT(25)
#define DMA_TDES1_CRC_DISABLE BIT(26)
#define DMA_TDES1_CHECKSUM_INSERTION_MASK GENMASK(28, 27)
#define DMA_TDES1_CHECKSUM_INSERTION_SHIFT 27
#define DMA_TDES1_FIRST_SEGMENT BIT(29)
#define DMA_TDES1_LAST_SEGMENT BIT(30)
#define DMA_TDES1_INTERRUPT BIT(31)
/* Bit definition of RDES0 register: DMA Rx descriptor status register */
/* RDES0 */
#define DMA_RDES0_PAYLOAD_CSUM_ERR BIT(0)
#define DMA_RDES0_CRC_ERROR BIT(1)
#define DMA_RDES0_DRIBBLING BIT(2)
#define DMA_RDES0_MII_ERROR BIT(3)
#define DMA_RDES0_RECEIVE_WATCHDOG BIT(4)
#define DMA_RDES0_FRAME_TYPE BIT(5)
#define DMA_RDES0_COLLISION BIT(6)
#define DMA_RDES0_IPC_CSUM_ERROR BIT(7)
#define DMA_RDES0_LAST_DESCRIPTOR BIT(8)
#define DMA_RDES0_FIRST_DESCRIPTOR BIT(9)
#define DMA_RDES0_VLAN_TAG BIT(10)
#define DMA_RDES0_OVERFLOW_ERROR BIT(11)
#define DMA_RDES0_LENGTH_ERROR BIT(12)
#define DMA_RDES0_SA_FILTER_FAIL BIT(13)
#define DMA_RDES0_DESCRIPTOR_ERROR BIT(14)
#define DMA_RDES0_ERROR_SUMMARY BIT(15)
#define DMA_RDES0_FRAME_LEN_MASK (0x3FFF << 16) /*GENMASK(29, 16)*/
#define DMA_RDES0_FRAME_LEN_SHIFT 16
#define DMA_RDES0_DA_FILTER_FAIL BIT(30)
#define DMA_RDES0_OWN BIT(31)
/* RDES1 */
#define DMA_RDES1_BUFFER1_SIZE_MASK GENMASK(10, 0)
#define DMA_RDES1_BUFFER2_SIZE_MASK GENMASK(21, 11)
#define DMA_RDES1_BUFFER2_SIZE_SHIFT 11
#define DMA_RDES1_SECOND_ADDRESS_CHAINED BIT(24)
#define DMA_RDES1_END_RING BIT(25)
#define DMA_RDES1_DISABLE_IC BIT(31)
/** DMA Status register defines **/
#define DMA_STATUS_GLPII 0x40000000 /* GMAC LPI interrupt */
#define DMA_STATUS_GPI 0x10000000 /* PMT interrupt */
#define DMA_STATUS_GMI 0x08000000 /* MMC interrupt */
#define DMA_STATUS_GLI 0x04000000 /* GMAC Line interface int */
#define DMA_STATUS_EB_MASK 0x00380000 /* Error Bits Mask */
#define DMA_STATUS_EB_TX_ABORT 0x00080000 /* Error Bits - TX Abort */
#define DMA_STATUS_EB_RX_ABORT 0x00100000 /* Error Bits - RX Abort */
#define DMA_STATUS_TS_MASK 0x00700000 /* Transmit Process State */
#define DMA_STATUS_RS_MASK 0x000e0000 /* Receive Process State */
#define DMA_STATUS_NIS 0x00010000 /* Normal Interrupt Summary */
#define DMA_STATUS_AIS 0x00008000 /* Abnormal Interrupt Summary */
#define DMA_STATUS_ERI 0x00004000 /* Early Receive Interrupt */
#define DMA_STATUS_FBI 0x00002000 /* Fatal Bus Error Interrupt */
#define DMA_STATUS_ETI 0x00000400 /* Early Transmit Interrupt */
#define DMA_STATUS_RWT 0x00000200 /* Receive Watchdog Timeout */
#define DMA_STATUS_RPS 0x00000100 /* Receive Process Stopped */
#define DMA_STATUS_RU 0x00000080 /* Receive Buffer Unavailable */
#define DMA_STATUS_RI 0x00000040 /* Receive Interrupt */
#define DMA_STATUS_UNF 0x00000020 /* Transmit Underflow */
#define DMA_STATUS_OVF 0x00000010 /* Receive Overflow */
#define DMA_STATUS_TJT 0x00000008 /* Transmit Jabber Timeout */
#define DMA_STATUS_TU 0x00000004 /* Transmit Buffer Unavailable */
#define DMA_STATUS_TPS 0x00000002 /* Transmit Process Stopped */
#define DMA_STATUS_TI 0x00000001 /* Transmit Interrupt */
#define DMA_STATUS_INIT 0xFFFFFFFF
/** DMA 操作模式寄存器 **/
#define DMA_OP_DT 0x04000000U /* No Dropping of TCP/IP csum Err Frame */
#define DMA_OP_RSF 0x02000000U /* Rx Store and Forward */
#define DMA_OP_DFF 0x01000000U /* */
#define DMA_OP_TSF 0x000200000U /* Tx Store and Forward */
#define DMA_OP_FTF 0x000100000U /* Flush Tx FIFO */
#define DMA_OP_TTC(x) ((x & 7) << 14) /* Tx Threshold Control ,• 000 64 , 001 128 , 010 192 ,011 256 ,100 40 , 101 32 , 110 24 , 111 16*/
#define DMA_OP_ST 0x000002000U /* Start/Stop Tx */
#define DMA_OP_RFD(x) ((x & 0x3) << 11) /* Threshold for DeActive Flow Control */
#define DMA_OP_RFA 0x000000600U /* Threshold for Active Flow Control */
#define DMA_OP_EFC 0x000000100U /* Enable HW Flow control */
#define DMA_OP_FEF 0x000000080U /* Forward Error Frame */
#define DMA_OP_FUF 0x000000040U /* Forward Undersize Good Frame */
#define DMA_OP_RTC 0x000000018U /* Rx Threshold Control */
#define DMA_OP_OSF 0x000000004U /* Operate On Second Mode */
#define DMA_OP_SR 0x00000002U /* Start/Stop Rx */
#define DMA_OP_CLEAR_MASK ((u32)0xF8DE3F23U)
#define DMA_OP_INIT (DMA_OP_SR | DMA_OP_RSF)
/** 中断使能寄存器 **/
#define DMA_INTR_ENA_TIE 0x00000001U /* Transmit Interrupt */
#define DMA_INTR_ENA_TSE 0x00000002U /* 传输停止启用 */
#define DMA_INTR_ENA_TUE 0x00000004U /* Transmit Buffer Unavailable */
#define DMA_INTR_ENA_THE 0x00000008U /* 发送 Jabber 超时启用 */
#define DMA_INTR_ENA_OVE 0x00000010U /* 溢出中断使能 */
#define DMA_INTR_ENA_UNE 0x00000020U /* 下溢中断使能 */
#define DMA_INTR_ENA_RIE 0x00000040U /* Receive Interrupt */
#define DMA_INTR_ENA_RUE 0x00000080U /* 接收缓冲区不可用启用 */
#define DMA_INTR_ENA_RSE 0x00000100U /* 接收已停止启用 */
#define DMA_INTR_ENA_RWE 0x00000200U /* 接收看门狗超时使能 */
#define DMA_INTR_ENA_ETE 0x00000400U /* 早期发送中断使能 */
#define DMA_INTR_ENA_FBE 0x00002000U /* Fatal Bus Error */
#define DMA_INTR_ENA_ERE 0x00004000U /* Early Receive */
#define DMA_INTR_ENA_AIE 0x00008000 /* Abnormal Summary */
#define DMA_INTR_ENA_NIE 0x00010000 /* Normal Summary */
#define DMA_INTR_DEFAULT (DMA_INTR_ENA_TIE | DMA_INTR_ENA_TSE | DMA_INTR_ENA_TUE | DMA_INTR_ENA_THE | DMA_INTR_ENA_OVE | DMA_INTR_ENA_UNE | DMA_INTR_ENA_RIE | DMA_INTR_ENA_RUE | DMA_INTR_ENA_RSE | DMA_INTR_ENA_RWE | DMA_INTR_ENA_ETE | DMA_INTR_ENA_FBE | DMA_INTR_ENA_ERE | DMA_INTR_ENA_AIE | DMA_INTR_ENA_NIE)
/** 丢帧和缓冲区溢出计数器寄存器 **/
#define DMA_MISSED_FRAME_CTR_CMIS 0x0000FFFFUDMA_MISSED_FRAME
#define DMA_MISSED_FRAME_CTR_OVMIS 0x00010000U
#define DMA_MISSED_FRAME_CTR_CFIFO 0x0ffe0000U
#define DMA_MISSED_FRAME_CTR_OVFIFO 0x10000000U
/** 接收中断看门狗定时器寄存器 **/
#define DMA_RX_WATCHDOG_RIWT 0x0000000fU
/** AXI_BUS_MOD **/
#define DMA_AXI_BUS_MOD_UNDEF 0x00000001U /* AXI 未定义的突发长度 */
#define DMA_AXI_BUS_MOD_BLEN4 0x00000002U /* AXI 突发长度 4 */
#define DMA_AXI_BUS_MOD_BLEN8 0x00000004U /* AXI 突发长度 8 */
#define DMA_AXI_BUS_MOD_BLEN16 0x00000008U /* AXI 突发长度 16 */
#define DMA_AXI_BUS_MOD_BLEN32 0x00000010U /* AXI 突发长度 32 */
#define DMA_AXI_BUS_MOD_BLEN64 0x00000020U /* AXI 突发长度 64 */
#define DMA_AXI_BUS_MOD_BLEN128 0x00000040U /* AXI 突发长度 128 */
#define DMA_AXI_BUS_MOD_BLEN256 0x00000080U /* AXI 突发长度 256 */
#define DMA_AXI_BUS_MOD_AXI_AAL 0x00001000U /* 地址对齐的节拍 */
#define DMA_AXI_BUS_MOD_RD_OSR_LMT(x) ((x & 0xf) << 16) /* XI 最大读取未决请求限制此值限 制 AXI 读取接口上的最大未完成请求。 */
#define DMA_AXI_BUS_MOD_WR_OSR_LMT(x) ((x & 0xf) << 20) /* AXI 最大写入未决请求限制此值 限制 AXI 写入接口上的最大未完成请求。 */
#define DMA_AXI_BUS_MOD_UNLCK_ON_MGK_RWK 0x40000000U
#define DMA_AXI_BUS_MOD_EN_LPI 0x80000000U
/** MMC Control **/
#define MMC_DEFAULT_MASK 0xffffffff
/* Common PHY Registers (AR8035) */
#define PHY_BCR_OFFSET ((u16)0x00) /* Transceiver Basic Control Register */
#define PHY_BSR_OFFSET ((u16)0x01) /* Transceiver Basic Status Register */
#define PHY_ID1_REG_OFFSET ((u16)0x02) /* PHY ID1 Identifier */
#define PHY_ID2_REG_OFFSET ((u16)0x03) /* PHY ID2 Identifier */
#define PHY_AUTO_NEGOTIATION_ADVERTISEMENT_OFFSET ((u16)0x04)
#define PHY_EXTENDED_CONTROL_REGISTER_OFFSET ((u16)0x9)
#define PHY_SPECIFIC_STATUS_OFFSET ((u16)0x11)
#define PHY_INTERRUPT_ENABLE_OFFSET ((u16)0x12)
#define PHY_INTERRUPT_STATUS_OFFSET ((u16)0x13)
#define PHY_DEBUG_ADDR_OFFSET ((u16)0x1D)
#define PHY_DEBUG_DATA_OFFSET ((u16)0x1E)
/* MII control register bit */
#define PHY_BCR_1000 0x0040 /* 1 = 1000mb when \
PHY_BCR_100 is also 1 */
#define PHY_BCR_COLL_TEST 0x0080 /* collision test */
#define PHY_BCR_FDX 0x0100 /* FDX =1, half duplex =0 */
#define PHY_BCR_RESTART 0x0200 /* restart auto negotiation */
#define PHY_BCR_ISOLATE 0x0400 /* isolate PHY from MII */
#define PHY_BCR_POWER_DOWN 0x0800 /* power down */
#define PHY_BCR_AUTO_EN 0x1000 /* auto-negotiation enable */
#define PHY_BCR_100 0x2000 /* 0 = 10mb, 1 = 100mb */
#define PHY_BCR_LOOPBACK 0x4000 /* 0 = normal, 1 = loopback */
#define PHY_BCR_RESET 0x8000 /* 0 = normal, 1 = PHY reset */
#define PHY_BCR_NORM_EN 0x0000 /* just enable the PHY */
#define PHY_BCR_DEF_0_MASK 0xca7f /* they must return zero */
#define PHY_BCR_RES_MASK 0x003f /* reserved bits,return zero */
#define PHY_ANAR_10TX_HD ((u16)0x0020)
#define PHY_ANAR_10TX_FD ((u16)0x0040)
#define PHY_ANAR_100TX_HD ((u16)0x0080)
#define PHY_ANAR_100TX_FD ((u16)0x0100)
#define PHY_ANAR_100T_4 ((u16)0x0200)
#define PHY_ANAR_PAUSE ((u16)0x0400)
#define PHY_ANAR_ASM_PAUSE ((u16)0x0800)
#define PHY_ANAR_REMORT_FAULT ((u16)0x2000)
#define PHY_ANAR_NEXT_PAGE ((u16)0x8000)
#define PHY_ANAR_PAUSE_MASK ((u16)0x0c00)
#define PHY_BSR_EXTENDED_STATUS ((u16)0x100)
#define PHY_EXTENDED_CONTROL_1000T_FD ((u16)0x200)
#define PHY_EXTENDED_CONTROL_1000T_HD ((u16)0x100)
#define PHY_RESET ((u16)0x8000U) /* PHY Reset */
#define PHY_LOOPBACK ((u16)0x4000U) /* Select loop-back mode */
#define PHY_FULLDUPLEX_1000M ((u16)0x2140U) /* Set the full-duplex mode at 1000 Mb/s */
#define PHY_HALFDUPLEX_1000M ((u16)0x2040U) /* Set the half-duplex mode at 1000 Mb/s */
#define PHY_FULLDUPLEX_100M ((u16)0x2100U) /* Set the full-duplex mode at 100 Mb/s */
#define PHY_HALFDUPLEX_100M ((u16)0x2000U) /* Set the half-duplex mode at 100 Mb/s */
#define PHY_FULLDUPLEX_10M ((u16)0x0100U) /* Set the full-duplex mode at 10 Mb/s */
#define PHY_HALFDUPLEX_10M ((u16)0x0000U) /* Set the half-duplex mode at 10 Mb/s */
#define PHY_AUTONEGOTIATION ((u16)0x1000U) /* Enable auto-negotiation function */
#define PHY_RESTART_AUTONEGOTIATION ((u16)0x0200U) /* Restart auto-negotiation function */
#define PHY_POWERDOWN ((u16)0x0800U) /* Select the power down mode */
#define PHY_ISOLATE ((u16)0x0400U) /* Isolate PHY from MII */
#define PHY_AUTONEGO_COMPLETE ((u16)0x0020U) /* Auto-Negotiation process completed */
#define PHY_LINKED_STATUS ((u16)0x0004U) /* Valid link established */
#define PHY_JABBER_DETECTION ((u16)0x0002U) /* Jabber condition detected */
#define PHY_SPECIFIC_STATUS_DUPLEX ((u16)0x2000) /* 0 is Half-duplex ,1 is Full-duplex */
#define PHY_SPECIFIC_STATUS_SPEED ((u16)0xc000) /* 0 is 10Mbps ,1 is 100Mbps , 2 is 1000Mbps */
#define PHY_INTERRUPT_ENABLE_WAKE_ON_LAN 0x00000001U /* Wake on LAN interrupt enable,0 Interrupt disable , 1 Interrupt enable */
#define PHY_INTERRUPT_ENABLE_POLARITY_CHANGED 0x00000002U /* Polarity Changed interrupt enable,0 Interrupt disable , 1 Interrupt enable */
#define PHY_INTERRUPT_ENABLE_WIRESPEED_DOWNGRADE 0x00000020U /* Wirespeed downgrade Interrupt ,0 Interrupt disable , 1 Interrupt enable*/
#define PHY_INTERRUPT_ENABLE_LINK_SUCCESS 0x00000400U /* Link success interrupt ,0 Interrupt disable , 1 Interrupt enable*/
#define PHY_INTERRUPT_ENABLE_LINK_FAIL 0x00000800U /* Link fail interrupt, 0 Interrupt disable , 1 Interrupt enable */
#define PHY_INTERRUPT_ENABLE_PAGE_RECEIVED 0x00001000U /* Page Received, 0 Interrupt disable , 1 Interrupt enable */
#define PHY_INTERRUPT_ENABLE_DUPLEX_CHANGED 0x00002000U /* Duplex Changed, 0 Interrupt disable , 1 Interrupt enable*/
#define PHY_INTERRUPT_ENABLE_SPEED_CHANGED 0x00004000U /* Speed Changed , 0 Interrupt disable , 1 Interrupt enable */
#define PHY_INTERRUPT_ENABLE_AUTO_NEGOTIATION_ERROR 0x00008000U /* Auto-Negotiation Error , 0 Interrupt disable , 1 Interrupt enable */
#define PHY_INTERRUPT_STATUS_WAKE_ON_LAN 0x00000001U /* Wake on LAN ,0 No Wake-on-LAN packet is received , 1 Wake-on-LAN packet is received */
#define PHY_INTERRUPT_STATUS_POLARITY_CHANGED 0x00000002U /* Polarity Changed ,0 Polarity changed , 1 Polarity not changed */
#define PHY_INTERRUPT_STATUS_WIRESPEED_DOWNGRADE 0x00000020U /* Wirespeed downgrade Interrupt ,0 No Smartspeed interrupt detected , 1 Smartspeed interrupt detected */
#define PHY_INTERRUPT_STATUS_LINK_SUCCESS 0x00000400U /* Link success interrupt ,0 Link up not happened , 1 Link up happened.*/
#define PHY_INTERRUPT_STATUS_LINK_FAIL 0x00000800U /* Link fail interrupt, 0 Link down not happened , 1 Link down happened. */
#define PHY_INTERRUPT_STATUS_PAGE_RECEIVED 0x00001000U /* Page Received, 0 Page not received , 1 Page received */
#define PHY_INTERRUPT_STATUS_DUPLEX_CHANGED 0x00002000U /* Duplex Changed, 0 Duplex not changed , 1 Duplex changed*/
#define PHY_INTERRUPT_STATUS_SPEED_CHANGED 0x00004000U /* Speed Changed , 0 Speed not changed , 1 Speed changed */
#define PHY_INTERRUPT_STATUS_AUTO_NEGOTIATION_ERROR 0x00008000U /* Auto-Negotiation Error , 0 No Auto-Negotiation Error , 1 Auto-Negotiation Error */
/**
* @name: FGmac_InitializeHw
* @msg: Mac层与Phy层参数
* @param {FGmac_Config_t} *Config Mac层 Phy层
* @return {s32} Common_status
*/
s32 FGmac_InitializeHw(FGmac_Config_t *Config);
/**
* @name: FGmac_ReadPHYRegister
* @msg: Phy
* @param {FGmac_Config_t} *Config Phy读取过程中需要的相关参数
* @param {u16} PHYReg Phy
* @param {u32} *RegValue
* @return {s32} Common_status
*/
s32 FGmac_ReadPHYRegister(FGmac_Config_t *Config, u16 PHYReg, u32 *RegValue);
/**
* @name: Gmac_WritePHYRegister
* @msg: Phy
* @param {FGmac_Config_t} *Config Phy读取过程中需要的相关参数
* @param {u16} PHYReg Phy
* @param {u32} RegValue
* @return {s32} Common_status
*/
s32 Gmac_WritePHYRegister(FGmac_Config_t *Config, u16 PHYReg, u32 RegValue);
/**
* @name: FGmac_TransmissionEnable
* @msg: 使 Gmac
* @param {FGmac_Config_t} *Config Mac的基地址
* @return {None}
*/
void FGmac_TransmissionEnable(FGmac_Config_t *Config);
/**
* @name: FGmac_TransmissionDisable
* @msg: Gmac
* @param {FGmac_Config_t} *Config Mac的基地址
* @return {None}
*/
void FGmac_TransmissionDisable(FGmac_Config_t *Config);
/**
* @name: FGmac_ReceptionEnable
* @msg: 使 Gmac
* @param {FGmac_Config_t} *Config Mac的基地址
* @return {None}
*/
void FGmac_ReceptionEnable(FGmac_Config_t *Config);
/**
* @name: FGmac_ReceptionDisable
* @msg: Gmac
* @param {FGmac_Config_t} *Config Mac的基地址
* @return {None}
*/
void FGmac_ReceptionDisable(FGmac_Config_t *Config);
/**
* @name: FGmac_DMAReceptionTransmissionEnable
* @msg: 使 Gmac DMA描述符接收与写入功能
* @param {FGmac_Config_t} *Config Mac的基地址
* @return {*}
*/
void FGmac_DMAReceptionTransmissionEnable(FGmac_Config_t *Config);
/**
* @name: FGmac_ReceptionTransmissionEnable
* @msg: 使 Gmac
* @param {FGmac_Config_t} *Config Mac的基地址
* @return {*}
*/
void FGmac_ReceptionTransmissionEnable(FGmac_Config_t *Config);
/**
* @name: FGmac_FlushTransmitFIFO
* @msg: Gmac FIFO
* @param {FGmac_Config_t} *Config Mac的基地址
* @return {*}
*/
void FGmac_FlushTransmitFIFO(FGmac_Config_t *Config);
/**
* @name: FGmac_DMATransmissionEnable
* @msg: 使 DMA描述符发送功能
* @param {FGmac_Config_t} *Config Mac的基地址
* @return {*}
*/
void FGmac_DMATransmissionEnable(FGmac_Config_t *Config);
/**
* @name: FGmac_DMATransmissionDisable
* @msg: DMA描述符发送功能
* @param {FGmac_Config_t} *Config Mac的基地址
* @return {*}
*/
void FGmac_DMATransmissionDisable(FGmac_Config_t *Config);
/**
* @name: FGmac_DMAReceptionEnable
* @msg: 使 DMA描述符接收功能
* @param {FGmac_Config_t} *Config Mac的基地址
* @return {*}
*/
void FGmac_DMAReceptionEnable(FGmac_Config_t *Config);
/**
* @name: FGmac_DMAReceptionEnable
* @msg: 使 DMA描述符接收功能
* @param {FGmac_Config_t} *Config Mac的基地址
* @return {*}
*/
void FGmac_DMAReceptionDisable(FGmac_Config_t *Config);
#endif // !

View File

@ -0,0 +1,174 @@
/*
 * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
 *
 * SPDX-License-Identifier: Apache-2.0.
 *
* @Date: 2021-04-07 09:53:07
* @LastEditTime: 2021-05-25 16:42:56
* @Description:  This files is for gmac irq
*
* @Modify History:
* Ver   Who        Date         Changes
* ----- ------     --------    --------------------------------------
*/
#include "ft_gmac_hw.h"
#include "ft_gmac.h"
#include "ft_status.h"
#include "ft_assert.h"
#include "ft_io.h"
#include "ft_debug.h"
#define GMAC_INTR_DEBUG_TAG "GMAC_INTR"
#define GMAC_INTR_DEBUG_I(format, ...) FT_DEBUG_PRINT_I(GMAC_INTR_DEBUG_TAG, format, ##__VA_ARGS__)
#define GMAC_INTR_DEBUG_E(format, ...) FT_DEBUG_PRINT_E(GMAC_INTR_DEBUG_TAG, format, ##__VA_ARGS__)
#define GMAC_INTR_DEBUG_W(format, ...) FT_DEBUG_PRINT_W(GMAC_INTR_DEBUG_TAG, format, ##__VA_ARGS__)
s32 FGmac_SetHandler(Ft_Gmac_t *Gmac, FGmac_IsrCallbackSelect_t SelectIndex, void *FuncPtr,
void *Args)
{
Ft_assertNonvoid(Gmac != NULL);
Ft_assertNonvoid(FuncPtr != NULL);
Ft_assertNonvoid(Gmac->IsReady == FT_COMPONENT_IS_READLY);
switch (SelectIndex)
{
case FT_GMAC_TX_COMPLETE_CB_ID:
/* code */
Gmac->SendHandler = FuncPtr;
Gmac->SendArgs = Args;
break;
case FT_GMAC_RX_COMPLETE_CB_ID:
Gmac->RecvHandler = FuncPtr;
Gmac->RecvArgs = Args;
break;
case FT_GMAC_DMA_ERROR_CB_ID:
Gmac->ErrorHandler = FuncPtr;
Gmac->ErrorArgs = Args;
break;
case FT_GMAC_MAC_PHY_STATUS_CB_ID:
Gmac->StatusHandler = FuncPtr;
Gmac->StatusArgs = Args;
break;
default:
return FST_FAILURE;
}
return FST_SUCCESS;
}
__STATIC_INLINE u32 FGmac_ErrorCheck(Ft_Gmac_t *Gmac)
{
u32 RegValue = 0;
u32 ErrIsr_RegValue = 0;
u32 RetValue = 0;
RegValue = Ft_in32(Gmac->Config.BaseAddress + DMA_STATUS_OFFSET);
ErrIsr_RegValue = Ft_in32(Gmac->Config.BaseAddress + DMA_INTR_ENA_OFFSET);
if (((RegValue & DMA_STATUS_TPS) == DMA_STATUS_TPS) && ((ErrIsr_RegValue & DMA_INTR_ENA_TSE) == DMA_INTR_ENA_TSE))
{
RetValue |= GMAC_ERROR_TRANSMIT_PROCESS_STOPPED;
}
if (((RegValue & DMA_STATUS_TU) == DMA_STATUS_TU) && ((ErrIsr_RegValue & DMA_INTR_ENA_TUE) == DMA_INTR_ENA_TUE))
{
RetValue |= GMAC_ERROR_TRANSMIT_UNAVAILABLE_STATUS;
}
if (((RegValue & DMA_STATUS_TJT) == DMA_STATUS_TJT) && ((ErrIsr_RegValue & DMA_INTR_ENA_THE) == DMA_INTR_ENA_THE))
{
RetValue |= GMAC_ERROR_TRANSMIT_JABBER_TIMEOUT;
}
if (((RegValue & DMA_STATUS_OVF) == DMA_STATUS_OVF) && ((ErrIsr_RegValue & DMA_INTR_ENA_OVE) == DMA_INTR_ENA_OVE))
{
RetValue |= GMAC_ERROR_RECEIVE_FIFO_OVERFLOW;
}
if (((RegValue & DMA_STATUS_UNF) == DMA_STATUS_UNF) && ((ErrIsr_RegValue & DMA_INTR_ENA_UNE) == DMA_INTR_ENA_UNE))
{
RetValue |= GMAC_ERROR_TRANSMIT_UNDERFLOW;
}
if (((RegValue & DMA_STATUS_RU) == DMA_STATUS_RU) && ((ErrIsr_RegValue & DMA_INTR_ENA_RUE) == DMA_INTR_ENA_RUE))
{
RetValue |= GMAC_ERROR_RECEIVE_BUFFER_UNAVAILABLE;
}
if (((RegValue & DMA_STATUS_RPS) == DMA_STATUS_RPS) && ((ErrIsr_RegValue & DMA_INTR_ENA_RSE) == DMA_INTR_ENA_RSE))
{
RetValue |= GMAC_ERROR_RECEIVE_PROCESS_STOPPED;
}
if (((RegValue & DMA_STATUS_RWT) == DMA_STATUS_RWT) && ((ErrIsr_RegValue & DMA_INTR_ENA_RWE) == DMA_INTR_ENA_RWE))
{
RetValue |= GMAC_ERROR_RECEIVE_WATCHDOG_TIMEOUT;
}
if (((RegValue & DMA_STATUS_ETI) == DMA_STATUS_ETI) && ((ErrIsr_RegValue & DMA_INTR_ENA_ETE) == DMA_INTR_ENA_ETE))
{
RetValue |= GMAC_ERROR_EARLY_TRANSMIT_INTERRUPT;
}
if (((RegValue & DMA_STATUS_FBI) == DMA_STATUS_FBI) && ((ErrIsr_RegValue & DMA_INTR_ENA_FBE) == DMA_INTR_ENA_FBE))
{
RetValue |= GMAC_ERROR_FATAL_BUS_ERROR;
}
if (0U == RetValue)
{
RetValue |= GMAC_ERROR_UNDEFINED;
}
Ft_printf("error RetValue %x \r\n", RetValue);
return RetValue;
}
void FGmac_IntrHandler(void *Args)
{
Ft_Gmac_t *Gmac;
u32 RegValue;
u32 MACRegValue;
Ft_assertVoid(Args != NULL);
Gmac = (Ft_Gmac_t *)Args;
RegValue = Ft_in32(Gmac->Config.BaseAddress + DMA_STATUS_OFFSET);
if ((RegValue)&DMA_STATUS_GLI)
{
MACRegValue = Ft_in32(Gmac->Config.BaseAddress + GMAC_MAC_MAC_PHY_STATUS);
if (Gmac->StatusHandler)
{
Gmac->StatusHandler(Gmac->StatusArgs, MACRegValue);
}
}
/* Frame received */
if ((RegValue & (DMA_STATUS_RI)) != 0)
{
if (Gmac->RecvHandler)
{
Gmac->RecvHandler(Gmac->RecvArgs);
}
Ft_out32(Gmac->Config.BaseAddress + DMA_STATUS_OFFSET, DMA_STATUS_RI);
}
else if ((RegValue & DMA_STATUS_TI) == DMA_STATUS_TI)
{
Ft_printf("DMA_STATUS_TI %x \r\n", RegValue);
Ft_printf("ti debug %x \r\n", Ft_in32(Gmac->Config.BaseAddress + GMAC_INTERNAL_MODULE_STATUS_OFFSET));
Ft_out32(Gmac->Config.BaseAddress + DMA_STATUS_OFFSET, DMA_STATUS_TI);
}
Ft_out32(Gmac->Config.BaseAddress + DMA_STATUS_OFFSET, DMA_STATUS_NIS);
/* DMA Error */
if ((Ft_in32(Gmac->Config.BaseAddress + DMA_STATUS_OFFSET) & DMA_STATUS_AIS) == DMA_STATUS_AIS)
{
if (Gmac->ErrorHandler)
Gmac->ErrorHandler(Gmac->ErrorArgs, FGmac_ErrorCheck(Gmac));
Ft_out32(Gmac->Config.BaseAddress + DMA_STATUS_OFFSET, Ft_in32(Gmac->Config.BaseAddress + DMA_STATUS_OFFSET));
}
}

View File

@ -0,0 +1,34 @@
/*
 * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
 *
 * SPDX-License-Identifier: Apache-2.0.
 *
* @Date: 2021-04-07 09:53:07
* @LastEditTime: 2021-05-25 16:43:06
* @Description:  This files is for gmac static init
*
* @Modify History:
* Ver   Who        Date         Changes
* ----- ------     --------    --------------------------------------
*/
#include "ft_gmac.h"
#include "ft_parameters.h"
extern FGmac_Config_t Gmac_ConfigTable[FT_GMAC_INSTANCES_NUM];
FGmac_Config_t *Ft_Gmac_LookupConfig(u32 InstanceId)
{
FGmac_Config_t *CfgPtr = NULL;
u32 Index;
for (Index = 0; Index < (u32)FT_GMAC_INSTANCES_NUM; Index++)
{
if (Gmac_ConfigTable[Index].InstanceId == InstanceId)
{
CfgPtr = &Gmac_ConfigTable[Index];
break;
}
}
return (FGmac_Config_t *)CfgPtr;
}

View File

@ -0,0 +1,107 @@
/*
 * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
 *
 * SPDX-License-Identifier: Apache-2.0.
 *
* @Date: 2021-04-27 17:55:31
* @LastEditTime: 2021-05-25 16:43:31
* @Description:  This files is for
*
* @Modify History:
* Ver   Who        Date         Changes
* ----- ------     --------    --------------------------------------
*/
#include "ft_gpio.h"
#include "ft_gpio_hw.h"
#include "ft_assert.h"
#include "ft_debug.h"
#define GPIO_MAX_PIN 7
#define GPIO_MAX_CTRL_ID 1
void FGpio_SetGroupModeA(FT_IN u32 ctrlId, FT_IN u8 pin, FT_IN u32 mode)
{
u32 RegVal;
Ft_assertNoneReturn(ctrlId <= GPIO_MAX_CTRL_ID);
Ft_assertNoneReturn(pin <= GPIO_MAX_PIN);
RegVal = FGpioA_ReadReg(ctrlId, GPIO_INTEN);
switch (mode)
{
case GPIO_MODE_GPIO:
RegVal &= ~(1 << pin);
break;
case GPIO_MODE_INT:
RegVal |= (1 << pin);
break;
default:
Ft_assertNoneReturn(0);
break;
}
FGpioA_WriteReg(ctrlId, GPIO_INTEN, RegVal);
return;
}
static void FGpio_SetPinInOutA(FT_IN u32 ctrlId, FT_IN u8 pin, FT_IN u8 inOut)
{
u32 RegVal;
Ft_assertNoneReturn(ctrlId <= GPIO_MAX_CTRL_ID);
Ft_assertNoneReturn(pin <= GPIO_MAX_PIN);
RegVal = FGpioA_ReadReg(ctrlId, GPIO_SWPORTA_DDR);
if (inOut != (RegVal & (0x1 << pin)))
{
if (GPIO_INPUT == inOut)
{
RegVal &= ~(0x1 << pin);
}
else if (GPIO_OUTPUT == inOut)
{
RegVal |= (0x1 << pin);
}
else
{
Ft_assertNoneReturn(0);
}
FGpioA_WriteReg(ctrlId, GPIO_SWPORTA_DDR, RegVal);
}
return;
}
u32 FGpio_ReadPinA(FT_IN u32 ctrlId, FT_IN u8 pin)
{
u32 RegVal;
u32 OnOff;
Ft_assertNoneReturn(ctrlId <= GPIO_MAX_CTRL_ID);
Ft_assertNoneReturn(pin <= GPIO_MAX_PIN);
FGpio_SetPinInOutA(ctrlId, pin, GPIO_INPUT);
RegVal = FGpioA_ReadReg(ctrlId, GPIO_EXT_PORTA);
OnOff = (RegVal & (0x1 << pin)) ? GPIO_ON : GPIO_OFF;
return OnOff;
}
void FGpio_WritePinA(FT_IN u32 ctrlId, FT_IN u8 pin, FT_IN u8 onOff)
{
u32 RegVal;
Ft_assertNoneReturn(ctrlId <= GPIO_MAX_CTRL_ID);
Ft_assertNoneReturn(pin <= GPIO_MAX_PIN);
Ft_assertNoneReturn((onOff == GPIO_OFF) || (onOff == GPIO_ON));
FGpio_SetPinInOutA(ctrlId, pin, GPIO_OUTPUT);
RegVal = FGpioA_ReadReg(ctrlId, GPIO_SWPORTA_DR);
if (GPIO_OFF == onOff)
{
RegVal &= ~(1 << pin);
}
else
{
RegVal |= (1 << pin);
}
FGpioA_WriteReg(ctrlId, GPIO_SWPORTA_DR, RegVal);
return;
}

View File

@ -0,0 +1,73 @@
/*
 * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
 *
 * SPDX-License-Identifier: Apache-2.0.
 *
* @Date: 2021-04-27 17:55:12
* @LastEditTime: 2021-04-30 14:38:45
* @Description:  This files is for
*
* @Modify History:
* Ver   Who        Date         Changes
* ----- ------     --------    --------------------------------------
*/
#ifndef FT_BSP_GPIO_H
#define FT_BSP_GPIO_H
#ifdef __cplusplus
extern "C"
{
#endif
#include "ft_types.h"
#include "ft_gpio_hw.h"
/* gpio mode: gpio/int */
#define GPIO_MODE_GPIO 0
#define GPIO_MODE_INT 1
/* define debug utilities */
#define FT_GPIO_DEBUG_TAG "FT_GPIO"
#define FT_GPIO_ENABLE_DEBUG
#define FT_GPIO_ERROR(format, ...) FT_DEBUG_PRINT_E(FT_GPIO_DEBUG_TAG, format, ##__VA_ARGS__)
#ifdef FT_GPIO_ENABLE_DEBUG
#define FT_GPIO_DEBUG_I(format, ...) FT_DEBUG_PRINT_I(FT_GPIO_DEBUG_TAG, format, ##__VA_ARGS__)
#define FT_GPIO_DEBUG_W(format, ...) FT_DEBUG_PRINT_W(FT_GPIO_DEBUG_TAG, format, ##__VA_ARGS__)
#else
#define FT_GPIO_DEBUG_I(format, ...)
#define FT_GPIO_DEBUG_W(format, ...)
#endif
/**
* @name: FGpio_SetGroupModeA
* @msg: set gpio mode, polling or intr
* @return {*}
* @param {FT_IN u32} ctrlId
* @param {FT_IN u8} pin
* @param {FT_IN u32} mode
*/
void FGpio_SetGroupModeA(FT_IN u32 CtrlId, FT_IN u8 Pin, FT_IN u32 Mode);
/**
* @name: FGpio_ReadPinA
* @msg: get gpio pin status
* @return {*}
* @param {FT_IN u32} ctrlId
* @param {FT_IN u8} pin
*/
u32 FGpio_ReadPinA(FT_IN u32 CtrlId, FT_IN u8 Pin);
/**
* @name: FGpio_WritePinA
* @msg: set gpio pin status
* @return {*}
* @param {FT_IN u32} ctrlId
* @param {FT_IN u8} pin
* @param {FT_IN u8} onOff
*/
void FGpio_WritePinA(FT_IN u32 CtrlId, FT_IN u8 Pin, FT_IN u8 OnOff);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,92 @@
/*
 * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
 *
 * SPDX-License-Identifier: Apache-2.0.
 *
* @Date: 2021-04-27 17:55:22
* @LastEditTime: 2021-04-28 08:39:20
* @Description:  This files is for
*
* @Modify History:
* Ver   Who        Date         Changes
* ----- ------     --------    --------------------------------------
*/
#ifndef FT_BSP_GPIO_HW_H
#define FT_BSP_GPIO_HW_H
#ifdef __cplusplus
extern "C"
{
#endif
#include "ft_types.h"
#include "ft_io.h"
#define GPIO_CTRL_ID_0 0
#define GPIO_CTRL_ID_1 1
/* base address of gpio register */
#define GPIO_CTRL0_PA_BASE 0x28004000
#define GPIO_CTRL1_PA_BASE 0x28005000
#define GPIO_GROUPA_OFFSET 0x0
#define GPIO_GROUPB_OFFSET 0xc
/* offset of register map */
#define GPIO_SWPORTA_DR 0x00 //A 组端口输出寄存器
#define GPIO_SWPORTA_DDR 0x04 //A 组端口方向控制寄存器
#define GPIO_EXT_PORTA 0x08 //A 组端口输入寄存器
#define GPIO_SWPORTB_DR 0x0c //B 组端口输出寄存器
#define GPIO_SWPORTB_DDR 0x10 //B 组端口方向控制寄存器
#define GPIO_EXT_PORTB 0x14 //B 组端口输入寄存器
#define GPIO_INTEN 0x18 //A 组端口中断使能寄存器
#define GPIO_INTMASK 0x1c //A 组端口中断屏蔽寄存器
#define GPIO_INTTYPE_LEVEL 0x20 //A 组端口中断等级寄存器
#define GPIO_INT_POLARITY 0x24 //A 组端口中断极性寄存器
#define GPIO_INTSTATUS 0x28 //A 组端口中断状态寄存器
#define GPIO_RAW_INTSTATUS 0x2c //A 组端口原始中断状态寄存器
#define GPIO_LS_SYNC 0x30 //配置中断同步寄存器
#define GPIO_DEBOUNCE 0x34 //防反跳配置寄存器
#define GPIO_PORTA_EOI 0x38 //A 组端口中断清除寄存器
/* misc marco */
#define GPIO_GROUP_A 0
#define GPIO_OFF 0
#define GPIO_ON 1
#define GPIO_INPUT 0
#define GPIO_OUTPUT 1
inline static u32 FGpio_GetBaseAddr(FT_IN u32 ctrlId, FT_IN u32 groupId)
{
static const u32 CtrlAddr[2] = {GPIO_CTRL0_PA_BASE, GPIO_CTRL1_PA_BASE};
static const u32 GroupOff[2] = {GPIO_GROUPA_OFFSET, GPIO_GROUPB_OFFSET};
return CtrlAddr[ctrlId] + GroupOff[groupId];
}
/**
* @name: FGpio_WriteReg
* @msg: write gpio register
* @param {u32} BaseAddress base addr of i2c
* @param {u32} RegOffset addr offset of i2c register
* @param {u32} RegisterValue val to be write into register
* @return {void}
*/
#define FGpioA_WriteReg(ctrlId, RegOffset, RegisterValue) Ft_out32(FGpio_GetBaseAddr(ctrlId, GPIO_GROUP_A) + (u32)RegOffset, (u32)RegisterValue)
/**
* @name: FGpio_ReadReg
* @msg: read gpio register
* @param {u32} BaseAddress base addr of i2c
* @param {u32} RegOffset addr offset of i2c register
* @return {u32} val read from register
*/
#define FGpioA_ReadReg(ctrlId, RegOffset) Ft_in32(FGpio_GetBaseAddr(ctrlId, GPIO_GROUP_A) + (u32)RegOffset)
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,510 @@
/*
 * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
 *
 * SPDX-License-Identifier: Apache-2.0.
 *
* @Date: 2021-04-07 09:53:07
* @LastEditTime: 2021-05-25 16:45:00
* @Description:  This files is for i2c user interface
*
* @Modify History:
* Ver   Who        Date         Changes
* ----- ------     --------    --------------------------------------
*/
#include <string.h>
#include <stdio.h>
#include "ft_mux.h"
#include "ft_i2c_hw.h"
#include "ft_i2c.h"
#include "ft_generic_timer.h"
/* reset val of register */
#define I2C_CON_DEFAULT 0x7F
#define I2C_TAR_DEFAULT 0x1055
#define I2C_SAR_DEFAULT 0x55
#define I2C_DATA_CMD_DEFAULT 0x0
#define I2C_SS_SCL_LCNT_DEFAULT 0x1D6
#define I2C_SS_SCL_HCNT_DEFAULT 0x190
#define I2C_FS_SCL_LCNT_DEFAULT 0x82
#define I2C_FS_SCL_HCNT_DEFAULT 0x3C
#define I2C_HS_SCL_LCNT_DEFAULT 0x10
#define I2C_HS_SCL_HCNT_DEFAULT 0x6
#define I2C_INTR_MASK_DEFAULT 0x8FF
//#define I2C_RX_TL_DEFAULT 0x0
//#define I2C_TX_TL_DEFAULT 0x0
#define I2C_SCL_HCNT_DEFAULT 0x2f
#define I2C_SCL_LCNT_DEFAULT 0x2f
//#define I2C_RX_TL_SET 0xff
//#define I2C_TX_TL_SET 0xff
#define I2C_RX_TL_BY_BYTE 0x0
#define I2C_TX_TL_BY_BYTE 0x0
#define I2C_RX_TL_BY_FIFO 0x01
#define I2C_TX_TL_BY_FIFO 0x01
LOCAL const u32 g_I2cSpeedMask[MAX_I2C_SPEED] = {I2C_STANDARD_SPEED_MASK,
I2C_FAST_SPEED_MASK,
I2C_HIGH_SPEED_MASK};
LOCAL const u32 g_I2cSclLcntReg[MAX_I2C_SPEED] = {I2C_SS_SCL_LCNT,
I2C_FS_SCL_LCNT, I2C_HS_SCL_LCNT};
LOCAL const u32 g_I2cSclHcntReg[MAX_I2C_SPEED] = {I2C_SS_SCL_HCNT,
I2C_FS_SCL_LCNT, I2C_HS_SCL_LCNT};
void FI2C_resetReg(u32 BaseAddr)
{
/* set default value for register */
FI2C_WriteReg(BaseAddr, I2C_CON, I2C_CON_DEFAULT);
FI2C_WriteReg(BaseAddr, I2C_TAR, I2C_TAR_DEFAULT);
FI2C_WriteReg(BaseAddr, I2C_SAR, I2C_SAR_DEFAULT);
FI2C_WriteReg(BaseAddr, I2C_DATA_CMD, I2C_DATA_CMD_DEFAULT);
FI2C_WriteReg(BaseAddr, I2C_SS_SCL_LCNT, I2C_SS_SCL_LCNT_DEFAULT);
FI2C_WriteReg(BaseAddr, I2C_SS_SCL_HCNT, I2C_SS_SCL_HCNT_DEFAULT);
FI2C_WriteReg(BaseAddr, I2C_FS_SCL_LCNT, I2C_FS_SCL_LCNT_DEFAULT);
FI2C_WriteReg(BaseAddr, I2C_FS_SCL_HCNT, I2C_FS_SCL_HCNT_DEFAULT);
FI2C_WriteReg(BaseAddr, I2C_HS_SCL_LCNT, I2C_HS_SCL_LCNT_DEFAULT);
FI2C_WriteReg(BaseAddr, I2C_HS_SCL_HCNT, I2C_HS_SCL_HCNT_DEFAULT);
FI2C_WriteReg(BaseAddr, I2C_INTR_MASK, I2C_INTR_MASK_DEFAULT);
FI2C_WriteReg(BaseAddr, I2C_RX_TL, I2C_RX_TL_DEFAULT);
FI2C_WriteReg(BaseAddr, I2C_TX_TL, I2C_TX_TL_DEFAULT);
}
inline LOCAL void FI2C_setSclClk(FT_IN u32 BaseAddr, FT_IN FI2C_SpeedType_t SpeedType,
FT_IN u32 SclLcnt, FT_IN u32 SclHcnt)
{
u32 SclLcntAddr = g_I2cSclLcntReg[SpeedType];
u32 SclHcntAddr = g_I2cSclHcntReg[SpeedType];
FI2C_WriteReg(BaseAddr, SclLcntAddr, SclLcnt);
FI2C_WriteReg(BaseAddr, SclHcntAddr, SclHcnt);
return;
}
inline LOCAL void FI2C_setCtrlParam(FT_IN u32 BaseAddr, FT_IN FI2C_SpeedType_t SpeedType, FT_IN bool_t Is7BitAddr)
{
u32 RegVal;
RegVal = I2C_CON_ME | g_I2cSpeedMask[SpeedType];
RegVal |= ((TRUE == Is7BitAddr) ? I2C_CON_MASTER_ADR_7BIT : I2C_CON_MASTER_ADR_10BIT);
RegVal |= I2C_CON_RESTART_EN | I2C_CON_SLAVE_DISABLE;
FI2C_WriteReg(BaseAddr, I2C_CON, RegVal);
return;
}
void FI2C_initMasterCfg(FT_IN FI2C_Instance_t id,
FT_IN FI2C_WorkMode_t mode,
FT_IN bool_t UseWRFifo,
FT_IN u32 PageSize,
FT_INOUT FI2C_Config_t *pCfg)
{
Ft_assertNoneReturn(NULL != pCfg);
pCfg->InstanceId = id;
pCfg->BaseAddress = g_FI2cRegBaseAddr[id];
pCfg->IrqNum = g_FI2cIrqNum[id];
pCfg->IrqPriority = I2C_DEFAULT_IRQ_PRIORITY;
pCfg->BusSpeed = I2C_STANDARD_SPEED;
pCfg->SclLcnt = I2C_SCL_LCNT_DEFAULT;
pCfg->SclHcnt = I2C_SCL_HCNT_DEFAULT;
pCfg->WRByFifo = UseWRFifo;
if (TRUE == pCfg->WRByFifo)
{
pCfg->RxThres = I2C_RX_TL_BY_FIFO;
pCfg->TxThres = I2C_TX_TL_BY_FIFO;
}
else
{
pCfg->RxThres = I2C_RX_TL_BY_BYTE;
pCfg->TxThres = I2C_TX_TL_BY_BYTE;
}
pCfg->Is7BitAddr = TRUE;
pCfg->BlockSize = PageSize;
if (I2C_POLLING_MODE == mode)
{
pCfg->IsPolling = TRUE;
}
else if (I2C_IRQ_MODE == mode)
{
pCfg->IsPolling = FALSE;
}
else
{
Ft_assertNoneReturn(0);
}
return;
}
void FI2C_initMaster(FT_IN FI2C_Instance_t id,
FT_IN FI2C_WorkMode_t mode,
FT_IN u32 SlaveAddr,
FT_IN bool_t UseWRFifo,
FT_IN u32 PageSize,
FT_INOUT FI2C_t *pDev)
{
u32 RxDepth;
u32 TxDepth;
Ft_assertNoneReturn(NULL != pDev);
memset(pDev, 0, sizeof(FI2C_t));
/* setup i2c bus mux */
Ft_setI2cMux(id);
/* setup i2c config as master */
FI2C_initMasterCfg(id, mode, UseWRFifo, PageSize, &pDev->Config);
pDev->SlaveAddr = SlaveAddr;
pDev->DelayHandle = Ft_GenericTimer_UsDelay;
/* init irq handler */
pDev->pRxEvent = NULL;
pDev->pTxEvent = NULL;
pDev->pIrqCallBack = NULL;
pDev->pWaitCallBack = NULL;
FI2C_DISABLE_I2C_BUS(pDev);
FI2C_CLR_ALL_IRQ_STATUS(pDev);
/* reset reg val */
FI2C_resetReg(pDev->Config.BaseAddress);
/* set scl high && low level */
FI2C_setSclClk(pDev->Config.BaseAddress,
pDev->Config.BusSpeed,
pDev->Config.SclLcnt,
pDev->Config.SclHcnt);
/* set ctrl parameters */
FI2C_setCtrlParam(pDev->Config.BaseAddress,
pDev->Config.BusSpeed,
pDev->Config.Is7BitAddr);
/* set rx & tx trigger level */
RxDepth = FI2C_GET_RX_BUFFER_DEPTH(pDev);
TxDepth = FI2C_GET_TX_BUFFER_DEPTH(pDev);
/* threshold shall not greater than depth */
FI2C_SET_TX_TL(pDev, FT_MIN(pDev->Config.TxThres, TxDepth));
FI2C_SET_RX_TL(pDev, FT_MIN(pDev->Config.RxThres, RxDepth));
pDev->IsReady = TRUE;
return;
}
void FI2C_deInitMaster(FT_INOUT FI2C_t *pDev)
{
/* assert no memory need to release */
pDev->IsReady = FALSE;
}
inline LOCAL void FI2C_sendRestartCmd(FT_IN u32 BaseAddr)
{
u32 RegVal = FI2C_ReadReg(BaseAddr, I2C_CON);
RegVal |= I2C_CON_RESTART_EN;
FI2C_WriteReg(BaseAddr, I2C_CON, RegVal);
}
inline LOCAL void FI2C_setTarAddr(FT_IN u32 BaseAddr, FT_IN u32 SlaveAddr)
{
u32 RegVal = (SlaveAddr & I2C_TAR_ADR_MASK);
FI2C_WriteReg(BaseAddr, I2C_TAR, RegVal);
}
inline LOCAL void FI2C_sendWriteCmd(FT_IN u32 BaseAddr, FT_IN u32 PageAddr)
{
u32 RegVal = I2C_DATA_CMD_RESTART | (PageAddr & I2C_DATA_CMD_DAT_MASK);
FI2C_WriteReg(BaseAddr, I2C_DATA_CMD, RegVal);
}
inline LOCAL void FI2C_sendStartReadCmd(FT_IN u32 BaseAddr, FT_IN u32 PageAddr)
{
/* send read cmd */
u32 RegVal = I2C_DATA_CMD_STOP | I2C_DATA_CMD_RESTART | (PageAddr & 0xff);
FI2C_WriteReg(BaseAddr, I2C_DATA_CMD, RegVal);
}
void FI2C_sendStopCmd(FT_IN u32 BaseAddr)
{
/* send stop signal */
u32 RegVal = I2C_DATA_CMD_STOP;
FI2C_WriteReg(BaseAddr, I2C_DATA_CMD, RegVal);
}
LOCAL bool_t FI2C_blockWaitForStatus(FT_IN u32 stMask, FT_INOUT FI2C_t *pDev)
{
u32 timeout = 0;
bool_t IsFree = FALSE;
Ft_assertNoneReturn(NULL != pDev);
/* Wait until Specific Status Bit in I2C_STATUS is 1 */
while ((!FI2C_CHECK_STATUS(pDev, stMask)) && (timeout < I2C_TIMEOUT))
{
pDev->DelayHandle(5000);
timeout++;
}
/* check if status wait successful or timeout */
if (I2C_TIMEOUT != timeout)
{
IsFree = TRUE;
}
else
{
FT_I2C_ERROR("wait status 0x%x failed!!! reg val is 0x%x",
stMask, FI2C_GET_STATUS(pDev));
}
return IsFree;
}
u32 FI2C_writeByByte(FT_IN u32 len, FT_IN u8 *pI2cBuf, FT_IN u8 PageAddr, FT_INOUT FI2C_t *pDev)
{
u32 loop;
bool_t isNotTimeout;
u32 ret = ERR_I2C_OK;
Ft_assertNoneReturn((NULL != pDev) && (NULL != pI2cBuf));
if (!pDev->IsReady)
{
return ERR_I2C_NOT_READY;
}
if (pDev->Config.BlockSize <= len)
{
return ERR_I2C_SIZE_TOO_LARGE;
}
FI2C_DISABLE_I2C_BUS(pDev);
FI2C_sendRestartCmd(pDev->Config.BaseAddress);
FI2C_setTarAddr(pDev->Config.BaseAddress, pDev->SlaveAddr);
FI2C_ENABLE_I2C_BUS(pDev);
FI2C_sendWriteCmd(pDev->Config.BaseAddress, PageAddr);
for (loop = 0; loop < len; loop++)
{
if (!pDev->Config.IsPolling)
{
FI2C_setIrq(pDev, I2C_IRQ_TX_EMPTY, TRUE);
}
pDev->DelayHandle(2);
FI2C_SET_TX_DATA(pDev, pI2cBuf[loop]);
/* wait until TX fifo is empty */
if (pDev->Config.IsPolling)
{
isNotTimeout = FI2C_blockWaitForStatus(I2C_STATUS_TFE, pDev);
if (!isNotTimeout)
{
ret = ERR_I2C_WRITE_TIMEOUT;
goto EXIT;
}
}
else
{
pDev->LastIrqErr = ERR_I2C_OK;
if (pDev->pWaitCallBack)
{
pDev->pWaitCallBack(I2C_IRQ_TYPE_TX_COMPLETE, pDev);
}
else
{
ret = ERR_I2C_INVALID_HANDLER;
goto EXIT;
}
if (ERR_I2C_OK != pDev->LastIrqErr)
{
ret = pDev->LastIrqErr;
goto EXIT;
}
}
pDev->DelayHandle(2);
}
EXIT:
FI2C_SEND_TX_STOP_CMD(pDev);
pDev->DelayHandle(2);
return ret;
}
u32 FI2C_readByByte(FT_IN u32 len, FT_OUT u8 *pI2cBuf, FT_IN u8 PageAddr, FT_INOUT FI2C_t *pDev)
{
u32 loop;
bool_t isNotTimeout;
u32 ret = ERR_I2C_OK;
Ft_assertNoneReturn((NULL != pDev) && (NULL != pI2cBuf));
if (!pDev->IsReady)
{
return ERR_I2C_NOT_READY;
}
FI2C_DISABLE_I2C_BUS(pDev);
FI2C_sendRestartCmd(pDev->Config.BaseAddress);
FI2C_CLR_ALL_IRQ_STATUS(pDev);
FI2C_setTarAddr(pDev->Config.BaseAddress, pDev->SlaveAddr);
FI2C_ENABLE_I2C_BUS(pDev);
/* assign page addr when start read */
FI2C_sendStartReadCmd(pDev->Config.BaseAddress, PageAddr);
/* read contents */
for (loop = 0; loop < len; loop++)
{
if (!pDev->Config.IsPolling)
{
FI2C_setIrq(pDev, I2C_IRQ_RX_FULL, TRUE);
}
FI2C_SEND_RX_NEXT_CMD(pDev);
pDev->DelayHandle(2);
/* wait until data reach and start fetch data */
if (pDev->Config.IsPolling)
{
isNotTimeout = FI2C_blockWaitForStatus(I2C_STATUS_RFNE, pDev);
if (!isNotTimeout)
{
ret = ERR_I2C_READ_TIMEOUT;
goto EXIT;
}
}
else
{
pDev->LastIrqErr = ERR_I2C_OK;
if (pDev->pWaitCallBack)
{
pDev->pWaitCallBack(I2C_IRQ_TYPE_RX_COMPLETE, pDev);
}
else
{
ret = ERR_I2C_INVALID_HANDLER;
goto EXIT;
}
if (ERR_I2C_OK != pDev->LastIrqErr)
{
ret = pDev->LastIrqErr;
goto EXIT;
}
}
pI2cBuf[loop] = FI2C_GET_RX_DATA(pDev);
pDev->DelayHandle(2);
}
EXIT:
FI2C_SEND_RX_STOP_CMD(pDev);
pDev->DelayHandle(2);
return ret;
}
u32 FI2C_writeByFifo(FT_IN u8 PageAddr, FT_INOUT FI2C_t *pDev)
{
u32 loop;
u32 ret = ERR_I2C_OK;
u32 timeout = I2C_TIMEOUT / 10;
Ft_assertNoneReturn(NULL != pDev);
if (!pDev->IsReady)
{
return ERR_I2C_NOT_READY;
}
if (pDev->Config.IsPolling)
{
return ERR_I2C_NOT_SUPPORT;
}
FI2C_DISABLE_I2C_BUS(pDev);
FI2C_sendRestartCmd(pDev->Config.BaseAddress);
FI2C_setTarAddr(pDev->Config.BaseAddress, pDev->SlaveAddr);
FI2C_ENABLE_I2C_BUS(pDev);
FI2C_sendWriteCmd(pDev->Config.BaseAddress, PageAddr);
/* enable TX Empty, disable Rx Full */
FI2C_setIrq(pDev, I2C_IRQ_TX_EMPTY, TRUE);
FI2C_setIrq(pDev, I2C_IRQ_RX_FULL, FALSE);
pDev->LastIrqErr = ERR_I2C_OK;
if (pDev->pWaitCallBack)
{
pDev->pWaitCallBack(I2C_IRQ_TYPE_TX_COMPLETE, pDev);
}
else
{
ret = ERR_I2C_INVALID_HANDLER;
}
if (ERR_I2C_OK != pDev->LastIrqErr)
{
ret = pDev->LastIrqErr;
}
return ret;
}
u32 FI2C_readByFifo(FT_IN u8 PageAddr, FT_INOUT FI2C_t *pDev)
{
u32 loop;
u32 ret = ERR_I2C_OK;
u32 timeout = I2C_TIMEOUT / 10;
Ft_assertNoneReturn((NULL != pDev));
if (!pDev->IsReady)
{
return ERR_I2C_NOT_READY;
}
if (pDev->Config.IsPolling)
{
return ERR_I2C_NOT_SUPPORT;
}
FI2C_DISABLE_I2C_BUS(pDev);
FI2C_sendRestartCmd(pDev->Config.BaseAddress);
FI2C_setTarAddr(pDev->Config.BaseAddress, pDev->SlaveAddr);
FI2C_ENABLE_I2C_BUS(pDev);
/* assign page addr when start read */
FI2C_sendStartReadCmd(pDev->Config.BaseAddress, PageAddr);
FI2C_setIrq(pDev, I2C_IRQ_RX_FULL, TRUE);
FI2C_setIrq(pDev, I2C_IRQ_TX_EMPTY, FALSE);
FI2C_SET_RX_TL(pDev, 1);
pDev->DelayHandle(2);
FT_I2C_DEBUG_I("rx tl is 0x%x irq mask 0x%x",
FI2C_GET_RX_TL(pDev),
FI2C_getIrqMask(pDev));
FI2C_SEND_RX_NEXT_CMD(pDev);
pDev->DelayHandle(2);
pDev->LastIrqErr = ERR_I2C_OK;
if (pDev->pWaitCallBack)
{
pDev->pWaitCallBack(I2C_IRQ_TYPE_RX_COMPLETE, pDev);
}
else
{
ret = ERR_I2C_INVALID_HANDLER;
}
if (ERR_I2C_OK != pDev->LastIrqErr)
{
ret = pDev->LastIrqErr;
}
FI2C_SET_RX_TL(pDev, 0);
return ret;
}

View File

@ -0,0 +1,197 @@
/*
 * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
 *
 * SPDX-License-Identifier: Apache-2.0.
 *
* @Date: 2021-04-07 09:53:07
* @LastEditTime: 2021-04-07 13:32:20
* @Description:  This files is for i2c user interface
*
* @Modify History:
* Ver   Who        Date         Changes
* ----- ------     --------    --------------------------------------
*/
#ifndef FT_BSP_I2C_H
#define FT_BSP_I2C_H
#ifdef __cplusplus
extern "C"
{
#endif
#include "ft_types.h"
#include "ft_debug.h"
#include "ft_assert.h"
#include "ft_error_code.h"
#include "ft_i2c_hw.h"
/* I2C Ctrl instance */
typedef enum
{
I2C_CTRL_ID_0 = 0,
I2C_CTRL_ID_1,
I2C_CTRL_ID_2,
I2C_CTRL_ID_3,
MAX_I2C_CTRL_ID,
} FI2C_Instance_t;
static const u32 g_FI2cIrqNum[MAX_I2C_CTRL_ID] = {
44, 45, 46, 47};
static const u32 g_FI2cRegBaseAddr[MAX_I2C_CTRL_ID] = {
I2C0_BASE_ADDRESS, I2C1_BASE_ADDRESS,
I2C2_BASE_ADDRESS, I2C3_BASE_ADDRESS};
#define I2C_DEFAULT_IRQ_PRIORITY 0
/* Type of I2C device */
typedef enum
{
I2C_MASTER_DEV = 0,
I2C_SLAVE_DEV,
MAX_I2C_DEV
} FI2C_DevType_t;
/* I2C work mode type */
typedef enum
{
I2C_POLLING_MODE = 0,
I2C_IRQ_MODE,
MAX_I2C_WORKMODE
} FI2C_WorkMode_t;
/* Type of I2C bus speed */
typedef enum
{
I2C_STANDARD_SPEED = 0,
I2C_FAST_SPEED,
I2C_HIGH_SPEED,
MAX_I2C_SPEED,
} FI2C_SpeedType_t;
/* I2C error code Submodule */
typedef enum
{
I2C_ERR_MODE_DEF = 0,
MAX_I2C_ERR_MODE,
} FI2C_Submodule_t;
/* I2C irq type */
typedef enum
{
I2C_IRQ_TYPE_NONE = 0,
I2C_IRQ_TYPE_TX_COMPLETE,
I2C_IRQ_TYPE_RX_COMPLETE,
MAX_I2C_IRQ_TYPE
} FI2C_IrqType_t;
/* I2C config info */
typedef struct
{
FI2C_Instance_t InstanceId; /* Id of I2C ctrl instance */
u32 BaseAddress; /* base address of I2C register */
FI2C_DevType_t WorkMode; /* work as master or slave */
FI2C_SpeedType_t BusSpeed; /* bus speed setting */
u32 SclLcnt;
u32 SclHcnt;
u32 RxThres;
u32 TxThres;
bool_t Is7BitAddr; /* TRUE: use 7 bit addr, FALSE: use 10 bit addr */
bool_t IsPolling; /* is polling */
u32 IrqNum; /* irq num of I2C in system */
u32 IrqPriority; /* irq priority */
u32 BlockSize; /* block size, for eeprom */
bool_t WRByFifo;
} FI2C_Config_t;
/* I2C RX/TX buffer */
typedef struct
{
u8 *BytePtr;
u32 TotalBytes;
u32 DataLength;
u32 CurIndex;
} FI2C_Buffer_t;
typedef void (*FI2C_IrqCallBackHandler_t)(FT_IN u32 IrqType,
FT_INOUT void *pDev,
FT_INOUT void *pArg);
typedef void (*FI2C_IrqWaitHandler_t)(FT_IN u32 IrqType,
FT_INOUT void *pDev);
typedef int32_t (*FI2C_DelayHandler_t)(FT_IN u32);
/* I2C device info */
typedef struct
{
FI2C_Config_t Config; /* Configuration data structure */
void *pRxEvent;
void *pTxEvent;
FI2C_IrqCallBackHandler_t pIrqCallBack;
FI2C_IrqWaitHandler_t pWaitCallBack;
u32 LastIrqErr;
FI2C_Buffer_t RxBuf;
FI2C_Buffer_t TxBuf;
FI2C_DelayHandler_t DelayHandle;
bool_t IsReady; /* Device is ininitialized and ready*/
u16 SlaveAddr; /* address of I2C slave device for master */
} FI2C_t;
void FI2C_initMaster(FT_IN FI2C_Instance_t id,
FT_IN FI2C_WorkMode_t mode,
FT_IN u32 SlaveAddr,
FT_IN bool_t UseWRFifo,
FT_IN u32 PageSize,
FT_INOUT FI2C_t *pDev);
u32 FI2C_writeByByte(FT_IN u32 len, FT_IN u8 *pI2cBuf, FT_IN u8 PageAddr,
FT_INOUT FI2C_t *pDev);
u32 FI2C_readByByte(FT_IN u32 len, FT_OUT u8 *pI2cBuf, FT_IN u8 PageAddr,
FT_INOUT FI2C_t *pDev);
u32 FI2C_setIrqHandler(FT_IN FI2C_IrqType_t IrqType, FT_IN FI2C_DelayHandler_t pHandler, FT_IN void *pArgs,
FT_INOUT FI2C_t *pDev);
void FI2C_irqHandler(void *pArgs);
void FI2C_irqHandler4Fifo(void *pArgs);
u32 FI2C_getIrqMask(FT_IN FI2C_t *pDev);
void FI2C_setIrqMask(FT_IN FI2C_t *pDev, FT_IN u32 mask);
void FI2C_setIrq(FT_IN FI2C_t *pDev, FT_IN u32 maskBit, FT_IN bool_t enable);
bool_t FI2C_checkIfIntr(FT_IN FI2C_t *pDev);
u32 FI2C_writeByFifo(FT_IN u8 PageAddr, FT_INOUT FI2C_t *pDev);
u32 FI2C_readByFifo(FT_IN u8 PageAddr, FT_INOUT FI2C_t *pDev);
void FI2C_deInitMaster(FT_INOUT FI2C_t *pDev);
#define FT_I2C_DEBUG_TAG "FT_I2C"
//#define FT_I2C_ENABLE_DEBUG
#define FT_I2C_ERROR(format, ...) FT_DEBUG_PRINT_E(FT_I2C_DEBUG_TAG, format, ##__VA_ARGS__)
#ifdef FT_I2C_ENABLE_DEBUG
#define FT_I2C_DEBUG_I(format, ...) FT_DEBUG_PRINT_I(FT_I2C_DEBUG_TAG, format, ##__VA_ARGS__)
#define FT_I2C_DEBUG_W(format, ...) FT_DEBUG_PRINT_W(FT_I2C_DEBUG_TAG, format, ##__VA_ARGS__)
#else
#define FT_I2C_DEBUG_I(format, ...)
#define FT_I2C_DEBUG_W(format, ...)
#endif
#define ERR_I2C_OK ERR_SUCCESS
#define ERR_I2C_NOT_READY FT_CODE_ERR(errModeI2c, I2C_ERR_MODE_DEF, 1)
#define ERR_I2C_WRITE_TIMEOUT FT_CODE_ERR(errModeI2c, I2C_ERR_MODE_DEF, 2)
#define ERR_I2C_READ_TIMEOUT FT_CODE_ERR(errModeI2c, I2C_ERR_MODE_DEF, 3)
#define ERR_I2C_SIZE_TOO_LARGE FT_CODE_ERR(errModeI2c, I2C_ERR_MODE_DEF, 4)
#define ERR_I2C_NOT_SUPPORT FT_CODE_ERR(errModeI2c, I2C_ERR_MODE_DEF, 5)
#define ERR_I2C_INVALID_PARAM FT_CODE_ERR(errModeI2c, I2C_ERR_MODE_DEF, 6)
#define ERR_I2C_INVALID_HANDLER FT_CODE_ERR(errModeI2c, I2C_ERR_MODE_DEF, 7)
#define ERR_I2C_INVALID_NO_MEM FT_CODE_ERR(errModeI2c, I2C_ERR_MODE_DEF, 8)
#define ERR_I2C_BUS_NOT_ENABLED FT_CODE_ERR(errModeI2c, I2C_ERR_MODE_DEF, 9)
#define ERR_I2C_EVT_TIMEOUT FT_CODE_ERR(errModeI2c, I2C_ERR_MODE_DEF, 0xA)
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,13 @@
/*
 * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
 *
 * SPDX-License-Identifier: Apache-2.0.
 *
* @Date: 2021-04-20 15:35:23
* @LastEditTime: 2021-04-20 15:35:24
* @Description:  This files is for
*
* @Modify History:
* Ver   Who        Date         Changes
* ----- ------     --------    --------------------------------------
*/

View File

@ -0,0 +1,321 @@
/*
 * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
 *
 * SPDX-License-Identifier: Apache-2.0.
 *
* @Date: 2021-04-07 09:53:07
* @LastEditTime: 2021-04-07 13:26:58
* @Description:  This files is for i2c register definition
*
* @Modify History:
* Ver   Who        Date         Changes
* ----- ------     --------    --------------------------------------
*/
#ifndef FT_BSP_I2C_HW_H
#define FT_BSP_I2C_HW_H
#ifdef __cplusplus
extern "C"
{
#endif
#include "ft_types.h"
#include "ft_io.h"
/* i2c 1~4 reg base address */
#define I2C0_BASE_ADDRESS 0x28006000U
#define I2C1_BASE_ADDRESS 0x28007000U
#define I2C2_BASE_ADDRESS 0x28008000U
#define I2C3_BASE_ADDRESS 0x28009000U
/* defines */
#define I2C_TIMEOUT 5000
#define I2C_MAX_READ_SIZE 1
#define SEM_TIMEOUT 2
/* Register Definition */
#define I2C_CON 0x00
#define I2C_TAR 0x04
#define I2C_SAR 0x08
#define I2C_HS_MADDR 0x0C
#define I2C_DATA_CMD 0x10
#define I2C_SS_SCL_HCNT 0x14
#define I2C_SS_SCL_LCNT 0x18
#define I2C_FS_SCL_HCNT 0x1C
#define I2C_FS_SCL_LCNT 0x20
#define I2C_HS_SCL_HCNT 0x24
#define I2C_HS_SCL_LCNT 0x28
#define I2C_INTR_STAT 0x2C
#define I2C_INTR_MASK 0x30
#define I2C_RAW_INTR_STAT 0x34
#define I2C_RX_TL 0x38
#define I2C_TX_TL 0x3C
#define I2C_CLR_INTR 0x40
#define I2C_CLR_RX_UNDER 0x44
#define I2C_CLR_RX_OVER 0x48
#define I2C_CLR_TX_OVER 0x4C
#define I2C_CLR_RD_REQ 0x50
#define I2C_CLR_TX_ABRT 0x54
#define I2C_CLR_RX_DONE 0x58
#define I2C_CLR_ACTIVITY 0x5c
#define I2C_CLR_STOP_DET 0x60
#define I2C_CLR_START_DET 0x64
#define I2C_CLR_GEN_CALL 0x68
#define I2C_ENABLE 0x6C
#define I2C_STATUS 0x70
#define I2C_TXFLR 0x74
#define I2C_RXFLR 0x78
#define I2C_TX_ABRT_SOURCE 0x80
#define I2C_SLV_DATA_NACK_ONLY 0x84
#define I2C_DMA_CR 0x88
#define I2C_DMA_TDLR 0x8c
#define I2C_DMA_RDLR 0x90
#define I2C_SDA_SETUP 0x94
#define I2C_ACK_GENERAL_CALL 0x98
#define I2C_ENABLE_STATUS 0x9C
#define I2C_COMP_PARAM_1 0xf4
#define I2C_COMP_VERSION 0xf8
#define I2C_COMP_TYPE 0xfc
#define I2C_RAW_INTR_STAT_RX_UNDER 0x1
#define I2C_RAW_INTR_STAT_RX_OVER 0x2
#define I2C_RAW_INTR_STAT_RX_FULL 0x4
#define I2C_RAW_INTR_STAT_TX_OVER 0x8
#define I2C_RAW_INTR_STAT_TX_EMPTY 0x10
/* Default parameters */
#define I2C_CON_ME (0x1 << 0)
#define I2C_CON_MS_SS (0x1 << 1)
#define I2C_CON_MS_FS (0x2 << 1)
#define I2C_CON_MS_HS (0x3 << 1)
#define I2C_CON_SLAVE_ADR_7BIT (0x0 << 3)
#define I2C_CON_SLAVE_ADR_10BIT (0x1 << 3)
#define I2C_CON_MASTER_ADR_7BIT (0x0 << 4)
#define I2C_CON_MASTER_ADR_10BIT (0x1 << 4)
#define I2C_CON_RESTART_EN (0x1 << 5)
#define I2C_CON_SLAVE_DISABLE (0x1 << 6)
/* 0110 0011 0x63 */
#define I2C_CON_DEFAULT_MASTER (I2C_CON_ME | I2C_CON_MS_FS /*I2C_CON_MS_SS*/ /* | I2C_CON_RESTART_EN*/ | \
I2C_CON_SLAVE_ADR_7BIT | I2C_CON_SLAVE_DISABLE)
#define I2C_CTR_DEFAULT (I2C_CON_ME | I2C_CON_MASTER_ADR_7BIT | \
I2C_CON_SLAVE_DISABLE)
#define I2C_IRQ_NONE_MASK 0x0
#define I2C_IRQ_ALL_MASK 0x8ff
#define I2C_TAR_STARTBYTE (0x1 << 10)
#define I2C_TAR_SPECIAL_STARTBYTE (0x1 << 11)
#define I2C_TAR_ADR_7BIT (0x0 << 12)
#define I2C_TAR_ADR_10BIT (0x1 << 12)
#define I2C_TAR_ADR_MASK 0x3ff /* bit [9: 0] */
#define I2C_SLAVE_DISABLE_DEFAULT 0
#define I2C_RESTART_EN_DEFAULT 1
#define I2C_10BITADDR_MASTER_DEFAULT 0
#define I2C_10BITADDR_SLAVE_DEFAULT 1
#define I2C_MAX_SPEED_MODE_DEFAULT 3
#define I2C_MASTER_MODE_DEFAULT 1
#define I2C_STANDARD_SPEED_MASK (0x01 << 1)
#define I2C_FAST_SPEED_MASK (0x02 << 1)
#define I2C_HIGH_SPEED_MASK (0x03 << 1)
#define I2C_DEFAULT_TAR_ADDR_DEFAULT 0x055
#define I2C_DEFAULT_SLAVE_ADDR_DEFAULT 0x055
#define I2C_COMP_VERSION_DEFAULT 0x3131352A
#define I2C_HS_MASTER_CODE_DEFAULT 1
#define I2C_SS_SCL_HIGH_COUNT_DEFAULT 0x0190
#define I2C_SS_SCL_LOW_COUNT_DEFAULT 0x01d6
#define I2C_FS_SCL_HIGH_COUNT_DEFAULT 0x003c
#define I2C_FS_SCL_LOW_COUNT_DEFAULT 0x0082
#define I2C_HS_SCL_HIGH_COUNT_DEFAULT 0x006
#define I2C_HS_SCL_LOW_COUNT_DEFAULT 0x0010
#define I2C_RX_TL_DEFAULT 0
#define I2C_TX_TL_DEFAULT 0
#define I2C_DEFAULT_SDA_SETUP_DEFAULT 0x64
#define I2C_DEFAULT_ACK_GENERAL_CALL_DEFAULT 1
#define I2C_DYNAMI2C_TAR_UPDATE_DEFAULT 1
#define I2C_RX_BUFFER_DEPTH_DEFAULT 8
#define I2C_TX_BUFFER_DEPTH_DEFAULT 8
#define I2C_ADD_ENCODED_PARAMS_DEFAULT 1
#define I2C_HAS_DMA_DEFAULT 0
#define I2C_INTR_IO_DEFAULT 0
#define I2C_HC_COUNT_VALUES_DEFAULT 0
#define APB_DATA_WIDTH_DEFAULT 0
#define I2C_SLV_DATA_NACK_ONLY_DEFAULT 0
#define I2C_USE_COUNTS_DEFAULT 0
#define I2C_CLK_TYPE_DEFAULT 1
#define I2C_CLOCK_PERIOD_DEFAULT 10
/* Raw Interrupt Status */
#define I2C_IRQ_NONE (0x0)
#define I2C_IRQ_RX_UNDER (0x01 << 0)
#define I2C_IRQ_RX_OVER (0x01 << 1)
#define I2C_IRQ_RX_FULL (0x01 << 2)
#define I2C_IRQ_TX_OVER (0x01 << 3)
#define I2C_IRQ_TX_EMPTY (0x01 << 4)
#define I2C_IRQ_RD_REQ (0x01 << 5)
#define I2C_IRQ_TX_ABRT (0x01 << 6)
#define I2C_IRQ_RX_DONE (0x01 << 7)
#define I2C_IRQ_ACTIVITY (0x01 << 8)
#define I2C_IRQ_STOP_DET (0x01 << 9)
#define I2C_IRQ_START_DET (0x01 << 10)
#define I2C_IRQ_GEN_CALL (0x01 << 11)
#define I2C_IRQ_ALL 0xFFF
/* Default IRQ Mask Bit Setting */
#define I2C_IRQ_DEFAULT_MASK (I2C_IRQ_RX_FULL | I2C_IRQ_TX_EMPTY | \
I2C_IRQ_TX_ABRT | I2C_IRQ_STOP_DET | \
I2C_IRQ_START_DET)
/* Data command stop bit */
#define I2C_DATA_CMD_WR_STOP_BIT (0x02 << 8) /* bit 8=0:W, bit 9=1: stop */
#define I2C_DATA_CMD_RD_STOP_BIT (0x03 << 8) /* bit 8=1:R, bit 9=1: stop */
#define I2C_DATA_CMD_DAT_MASK 0xff /* bit [7:0] , TX and RX data */
#define I2C_DATA_CMD_WR (0x00 << 8)
#define I2C_DATA_CMD_RD (0x01 << 8)
#define I2C_DATA_CMD_STOP (0x01 << 9)
#define I2C_DATA_CMD_RESTART (0X01 << 10)
/* I2C TX Abort Source*/
#define I2C_ABRT_7B_ADDR_NOACK 0x001
#define I2C_ABRT_10_ADDR1_NOACK 0x002
#define I2C_ABRT_10_ADDR2_NOACK 0x004
#define I2C_ABRT_TXDATA_NOACK 0x008
#define I2C_ABRT_GCALL_NOACK 0x010
#define I2C_ABRT_GCALL_READ 0x020
#define I2C_ABRT_HS_ACKDET 0x040
#define I2C_ABRT_SBYTE_ACKDET 0x080
#define I2C_ABRT_HS_NORSTRT 0x100
#define I2C_ABRT_SBYTE_NORSTRT 0x200
#define I2C_ABRT_10B_RD_NORSTRT 0x400
#define I2C_ABRT_MASTER_DIS 0x800
#define I2C_ABRT_ARB_LOST 0x1000
#define I2C_ABRT_SLVFLUSH_TXFIFO 0x2000
#define I2C_ABRT_SLV_ARBLOST 0x5000
#define I2C_ABRT_SLVRD_INTX 0x8000
/* Minimum High and Low period in nanosecends */
#define SS_MIN_SCL_HIGH 4000
#define SS_MIN_SCL_LOW 4700
#define FS_MIN_SCL_HIGH 600
#define FS_MIN_SCL_LOW 1300
#define HS_MIN_SCL_HIGH_100PF 60
#define HS_MIN_SCL_LOW_100PF 120
/* I2C_STATUS (RO) */
#define I2C_STATUS_ACTIVITY (0x1 << 0) /* I2C ctrl is enabled */
#define I2C_STATUS_TFNF (0x1 << 1) /* TX FIFO is not full */
#define I2C_STATUS_TFE (0x1 << 2) /* TX FIFO is empty */
#define I2C_STATUS_RFNE (0x1 << 3) /* RX FIFO is not empty */
#define I2C_STATUS_RFF (0x1 << 4) /* RX FIFO is full */
#define I2C_STATUS_MST_ACTIVITY (0x1 << 5) /* Master is not idle */
#define I2C_STATUS_SLV_ACTIVITY (0x1 << 6) /* Slave is not idle */
/* Interrupts status */
#define I2C_INTR_RX_UNDER (0x1 << 0)
#define I2C_INTR_RX_OVER (0x1 << 1)
#define I2C_INTR_RX_FULL (0x1 << 2)
#define I2C_INTR_TX_OVER (0x1 << 3)
#define I2C_INTR_TX_EMPTY (0x1 << 4)
#define I2C_INTR_RD_REQ (0x1 << 5)
#define I2C_INTR_TX_ABRT (0x1 << 6)
#define I2C_INTR_RX_DONE (0x1 << 7)
#define I2C_INTR_ACTIVITY (0x1 << 8)
#define I2C_INTR_STOP_DET (0x1 << 9)
#define I2C_INTR_START_DET (0x1 << 10)
#define I2C_INTR_GEN_CALL (0x1 << 11)
#define I2C_TX_BUFFER_DEPTH_MASK 0xFF0000 /* bit [23: 16] */
#define I2C_RX_BUFFER_DEPTH_MASK 0x00FF00 /* bit [15: 8] */
#define I2C_INTR_MAX_BITS 12
#define I2C_ENABLE_CONTROLLER 0x01
#define I2C_DISABLE_CONTROLLER 0x00
#define I2C_DATA_CMD_READ (0x01 << 8)
#define I2C_DATA_CMD_WRITE (0x00 << 8)
#define I2C_TAR_DEFAULT_ADDR 0x55
#define FT2000_I2C_CLK (48000000) /* I2C clock */
/**
* @name: FI2c_WriteReg
* @msg: write i2c register
* @param {u32} BaseAddress base addr of i2c
* @param {u32} RegOffset addr offset of i2c register
* @param {u32} RegisterValue val to be write into register
* @return {void}
*/
#define FI2C_WriteReg(BaseAddress, RegOffset, RegisterValue) Ft_out32(BaseAddress + (u32)RegOffset, (u32)RegisterValue)
/**
* @name: FI2c_ReadReg
* @msg: read i2c register
* @param {u32} BaseAddress base addr of i2c
* @param {u32} RegOffset addr offset of i2c register
* @return {u32} val read from register
*/
#define FI2C_ReadReg(BaseAddress, RegOffset) Ft_in32(BaseAddress + (u32)RegOffset)
/*
* the following macros convert from BCD to binary and back.
* Be careful that the arguments are chars, only char width returned.
*/
#define BCD_TO_BIN(bcd) ((((((bcd)&0xf0) >> 4) * 10) + ((bcd)&0xf)) & 0xff)
#define BIN_TO_BCD(bin) (((((bin) / 10) << 4) + ((bin) % 10)) & 0xff)
#define FI2C_GET_BASE_ADDR(pDev) ((pDev)->Config.BaseAddress)
#define FI2C_ENABLE_I2C_BUS(pDev) (FI2C_WriteReg(FI2C_GET_BASE_ADDR(pDev), I2C_ENABLE, I2C_ENABLE_CONTROLLER))
#define FI2C_DISABLE_I2C_BUS(pDev) (FI2C_WriteReg(FI2C_GET_BASE_ADDR(pDev), I2C_ENABLE, I2C_DISABLE_CONTROLLER))
#define FI2C_IS_I2C_BUS_ENABLED(pDev) (FI2C_ReadReg(FI2C_GET_BASE_ADDR(pDev), I2C_ENABLE))
#define FI2C_GET_STATUS(pDev) (FI2C_ReadReg(FI2C_GET_BASE_ADDR(pDev), I2C_STATUS))
#define FI2C_CHECK_STATUS(pDev, stMask) (FI2C_GET_STATUS(pDev) & (stMask))
#define FI2C_CLR_ALL_IRQ_STATUS(pDev) (FI2C_ReadReg(FI2C_GET_BASE_ADDR(pDev), I2C_CLR_INTR))
#define FI2C_GET_IRQ_STATUS(pDev) (FI2C_ReadReg(FI2C_GET_BASE_ADDR(pDev), I2C_INTR_STAT))
#define FI2C_GET_IRQ_MASK(pDev) (FI2C_ReadReg(FI2C_GET_BASE_ADDR(pDev), I2C_INTR_MASK))
#define FI2C_SET_IRQ_MASK(pDev, mask) (FI2C_WriteReg(FI2C_GET_BASE_ADDR(pDev), I2C_INTR_MASK, (mask)))
#define FI2C_GET_TX_TL(pDev) (FI2C_ReadReg(FI2C_GET_BASE_ADDR(pDev), I2C_TX_TL))
#define FI2C_GET_RX_TL(pDev) (FI2C_ReadReg(FI2C_GET_BASE_ADDR(pDev), I2C_RX_TL))
#define FI2C_SET_TX_TL(pDev, TxThres) (FI2C_WriteReg(FI2C_GET_BASE_ADDR(pDev), I2C_TX_TL, (TxThres)))
#define FI2C_SET_RX_TL(pDev, RxThres) (FI2C_WriteReg(FI2C_GET_BASE_ADDR(pDev), I2C_RX_TL, (RxThres)))
#define FI2C_GET_TXFLR(pDev) (FI2C_ReadReg(FI2C_GET_BASE_ADDR(pDev), I2C_TXFLR))
#define FI2C_GET_RXFLR(pDev) (FI2C_ReadReg(FI2C_GET_BASE_ADDR(pDev), I2C_RXFLR))
#define FI2C_CLR_IRQ_RX_OVER(pDev) (FI2C_ReadReg(FI2C_GET_BASE_ADDR(pDev), I2C_CLR_RX_OVER))
#define FI2C_CLR_IRQ_TX_OVER(pDev) (FI2C_ReadReg(FI2C_GET_BASE_ADDR(pDev), I2C_CLR_TX_OVER))
#define FI2C_GET_COMP_PARAM_1(pDev) (FI2C_ReadReg(FI2C_GET_BASE_ADDR(pDev), I2C_COMP_PARAM_1))
#define FI2C_GET_TX_BUFFER_DEPTH(pDev) ((I2C_TX_BUFFER_DEPTH_MASK & FI2C_GET_COMP_PARAM_1(pDev)) >> 16)
#define FI2C_GET_RX_BUFFER_DEPTH(pDev) ((I2C_RX_BUFFER_DEPTH_MASK & FI2C_GET_COMP_PARAM_1(pDev)) >> 8)
#define FI2C_SEND_TX_STOP_CMD(pDev) (FI2C_WriteReg(FI2C_GET_BASE_ADDR(pDev), I2C_DATA_CMD, I2C_DATA_CMD_STOP))
#define FI2C_SET_TX_DATA(pDev, data) (FI2C_WriteReg(FI2C_GET_BASE_ADDR(pDev), I2C_DATA_CMD, ((u32)(data)&I2C_DATA_CMD_DAT_MASK)))
#define FI2C_GET_RX_DATA(pDev) (u8)(I2C_DATA_CMD_DAT_MASK & (FI2C_ReadReg(FI2C_GET_BASE_ADDR(pDev), I2C_DATA_CMD)))
#define FI2C_SEND_RX_NEXT_CMD(pDev) (FI2C_WriteReg(FI2C_GET_BASE_ADDR(pDev), I2C_DATA_CMD, I2C_DATA_CMD_STOP | I2C_DATA_CMD_RESTART | I2C_DATA_CMD_RD))
#define FI2C_SEND_RX_STOP_CMD(pDev) (FI2C_WriteReg(FI2C_GET_BASE_ADDR(pDev), I2C_DATA_CMD, I2C_DATA_CMD_STOP | I2C_DATA_CMD_RD))
void FI2C_resetReg(u32 BaseAddr);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,182 @@
/*
 * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
 *
 * SPDX-License-Identifier: Apache-2.0.
 *
* @Date: 2021-04-20 15:35:44
* @LastEditTime: 2021-05-25 16:44:45
* @Description:  This files is for
*
* @Modify History:
* Ver   Who        Date         Changes
* ----- ------     --------    --------------------------------------
*/
#include "ft_i2c.h"
void FI2C_irqHandler(void *pArgs)
{
FI2C_t *pDev;
u32 RegVal;
FI2C_IrqType_t IrqType = I2C_IRQ_TYPE_NONE;
Ft_assertNoneReturn(NULL != pArgs);
pDev = (FI2C_t *)pArgs;
RegVal = FI2C_GET_IRQ_STATUS(pDev);
if (I2C_IRQ_RX_FULL & RegVal)
{
IrqType = I2C_IRQ_TYPE_RX_COMPLETE;
}
else if (I2C_IRQ_TX_EMPTY & RegVal)
{
IrqType = I2C_IRQ_TYPE_TX_COMPLETE;
}
if ((NULL != pDev->pIrqCallBack) && (I2C_IRQ_TYPE_NONE != IrqType))
{
pDev->pIrqCallBack(IrqType, pDev, NULL);
}
if (I2C_IRQ_TYPE_RX_COMPLETE == IrqType)
{
FI2C_setIrq(pDev, I2C_IRQ_RX_FULL, FALSE);
}
else if (I2C_IRQ_TYPE_TX_COMPLETE == IrqType)
{
FI2C_setIrq(pDev, I2C_IRQ_TX_EMPTY, FALSE);
}
FI2C_CLR_ALL_IRQ_STATUS(pDev);
return;
}
void FI2C_irqHandler4Fifo(void *pArgs)
{
FI2C_t *pDev;
u32 RegVal;
u32 BytesToRx;
FI2C_IrqType_t IrqType = I2C_IRQ_TYPE_NONE;
Ft_assertNoneReturn(NULL != pArgs);
pDev = (FI2C_t *)pArgs;
/* check if i2c controller is enabled */
if (!FI2C_IS_I2C_BUS_ENABLED(pDev))
{
pDev->LastIrqErr = ERR_I2C_BUS_NOT_ENABLED;
return;
}
/* check there is no interrupt */
if (!FI2C_checkIfIntr(pDev))
{
pDev->LastIrqErr = ERR_I2C_INVALID_PARAM;
return;
}
/* read interrupt status */
RegVal = FI2C_GET_IRQ_STATUS(pDev);
if (I2C_IRQ_RX_FULL & RegVal)
{
IrqType = I2C_IRQ_TYPE_RX_COMPLETE;
BytesToRx = FI2C_GET_RXFLR(pDev);
while ((pDev->RxBuf.CurIndex < pDev->RxBuf.DataLength) &&
(0 < BytesToRx))
{
/* read one byte */
pDev->RxBuf.BytePtr[pDev->RxBuf.CurIndex] = FI2C_GET_RX_DATA(pDev);
pDev->RxBuf.CurIndex++;
BytesToRx--;
pDev->DelayHandle(10);
/* read next byte */
if (pDev->RxBuf.CurIndex != pDev->RxBuf.DataLength)
{
FI2C_SEND_RX_NEXT_CMD(pDev);
}
else
{
FI2C_SEND_RX_STOP_CMD(pDev);
pDev->DelayHandle(10);
FI2C_setIrq(pDev, I2C_IRQ_RX_FULL, FALSE);
}
}
}
else if (I2C_IRQ_TX_EMPTY & RegVal)
{
IrqType = I2C_IRQ_TYPE_TX_COMPLETE;
if (pDev->TxBuf.CurIndex == pDev->TxBuf.DataLength)
{
FI2C_SEND_TX_STOP_CMD(pDev);
pDev->DelayHandle(10);
FI2C_setIrq(pDev, I2C_IRQ_TX_EMPTY, FALSE);
}
else
{
FI2C_SET_TX_DATA(pDev, pDev->TxBuf.BytePtr[pDev->TxBuf.CurIndex]);
pDev->TxBuf.CurIndex++;
}
}
if ((NULL != pDev->pIrqCallBack) && (I2C_IRQ_TYPE_NONE != IrqType))
{
pDev->pIrqCallBack(IrqType, pDev, NULL);
}
pDev->LastIrqErr = ERR_I2C_OK;
return;
}
u32 FI2C_getIrqMask(FT_IN FI2C_t *pDev)
{
u32 RegVal;
Ft_assertNoneReturn(NULL != pDev);
RegVal = FI2C_GET_IRQ_MASK(pDev);
return RegVal;
}
void FI2C_setIrqMask(FT_IN FI2C_t *pDev, FT_IN u32 mask)
{
u32 RegVal;
Ft_assertNoneReturn(NULL != pDev);
RegVal = mask & I2C_IRQ_ALL_MASK;
FI2C_SET_IRQ_MASK(pDev, RegVal);
return;
}
void FI2C_setIrq(FT_IN FI2C_t *pDev, FT_IN u32 maskBit, FT_IN bool_t enable)
{
Ft_assertNoneReturn(0x0 != maskBit);
if (TRUE == enable)
{
FI2C_setIrqMask(pDev, FI2C_getIrqMask(pDev) | maskBit);
}
else
{
FI2C_setIrqMask(pDev, FI2C_getIrqMask(pDev) & (~maskBit));
}
return;
}
bool_t FI2C_checkIfIntr(FT_IN FI2C_t *pDev)
{
u32 RegVal;
Ft_assertNoneReturn(NULL != pDev);
RegVal = FI2C_ReadReg(FI2C_GET_BASE_ADDR(pDev), I2C_RAW_INTR_STAT);
if (0 == (RegVal & (~I2C_IRQ_ACTIVITY)))
{
return FALSE;
}
else
{
return TRUE;
}
}

View File

@ -0,0 +1,20 @@
/*
 * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
 *
 * SPDX-License-Identifier: Apache-2.0.
 *
* @Date: 2021-04-07 09:53:07
* @LastEditTime: 2021-04-07 13:27:24
* @Description:  This files is for i2c test cases
*
* @Modify History:
* Ver   Who        Date         Changes
* ----- ------     --------    --------------------------------------
*/
#include <time.h>
#include <string.h>
#include "ft_i2c_hw.h"
#include "ft_i2c.h"
#include "ft_status.h"
#include "ft_printf.h"

View File

@ -0,0 +1,585 @@
/*
 * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
 *
 * SPDX-License-Identifier: Apache-2.0.
*
* @Date: 2021-04-05 22:15:53
* @LastEditTime: 2021-05-25 16:45:36
* @Description:  Description of file
* @Modify History:
* * * Ver   Who        Date         Changes
* * ----- ------     --------    --------------------------------------
* * 1.00 hh 2021.04-06 init
*/
#include "ft_qspi.h"
#include "qspi_hw.h"
#include "ft_io.h"
#include "ft_assert.h"
#include "ft_types.h"
#include "string.h"
#include "ft_debug.h"
#define FTQSPI_DEBUG_TAG "FTQSPI"
#define FTQSPI_DEBUG_I(format, ...) FT_DEBUG_PRINT_I(FTQSPI_DEBUG_TAG, format, ##__VA_ARGS__)
#define FTQSPI_DEBUG_E(format, ...) FT_DEBUG_PRINT_E(FTQSPI_DEBUG_TAG, format, ##__VA_ARGS__)
#define FTQSPI_DEBUG_W(format, ...) FT_DEBUG_PRINT_W(FTQSPI_DEBUG_TAG, format, ##__VA_ARGS__)
ft_error_t FQSpi_CfgInitialize(FQSpi_t *pQspi, FQSpi_Config_t *pConfig)
{
Ft_assertNonvoid(pQspi != NULL);
Ft_assertNonvoid(pConfig != NULL);
pQspi->config = *pConfig;
pQspi->isReady = FT_COMPONENT_IS_READLY;
FQSpi_Reset(pQspi);
return FQSPI_SUCCESS;
}
/**
* @name: FQSpi_MemcpyToReg
* @msg: Memory copy To Register
* @in param {FQSpi_t} *pQspi
* @in param {u8} *buf
* @in param {u32} length
* @return {ft_error_t}
*/
static ft_error_t FQSpi_MemcpyToReg(FQSpi_t *pQspi, FT_IN u8 *buf, u32 length)
{
u32 val = 0;
FQSpi_Config_t *pConfig = NULL;
Ft_assertNonvoid(pQspi != NULL);
Ft_assertNonvoid(pQspi->isReady == FT_COMPONENT_IS_READLY);
pConfig = &pQspi->config;
if (!buf || (length > 4))
{
return FQSPI_FAILURE;
}
if (1 == length)
{
val = buf[0];
}
else if (2 == length)
{
val = buf[1];
val = (val << 8) + buf[0];
}
else if (3 == length)
{
val = buf[2];
val = (val << 8) + buf[1];
val = (val << 8) + buf[0];
}
else if (4 == length)
{
val = buf[3];
val = (val << 8) + buf[2];
val = (val << 8) + buf[1];
val = (val << 8) + buf[0];
}
Ft_out32(pConfig->baseAddress + FT_REG_QSPI_LD_PORT_OFFSET, val);
return FQSPI_SUCCESS;
}
/**
* @name: FQSpi_MemcpyFromReg
* @msg: Memory copy from Register
* @in param {FT_INFQSpi_t} *pQspi
* @out param {u8} *buf
* @in param {u32} length
* @return {*}
*/
static ft_error_t FQSpi_MemcpyFromReg(FQSpi_t *pQspi, u8 *buf, u32 length)
{
s32 i;
u32 val = 0;
FQSpi_Config_t *pConfig = NULL;
Ft_assertNonvoid(pQspi != NULL);
Ft_assertNonvoid(pQspi->isReady == FT_COMPONENT_IS_READLY);
pConfig = &pQspi->config;
for (i = 0; i < length; i++)
{
/* code */
if (0 == i % 4)
{
val = Ft_in32(pConfig->baseAddress + FT_REG_QSPI_LD_PORT_OFFSET);
}
buf[i] = (u8)(val >> (i % 4) * 8) & 0xff;
}
return FQSPI_SUCCESS;
}
/**
* @name: FQSpi_FlashRead
* @msg: Reads bytes data from flash addr to buf
* @in param pQspi:
* @in param cmd: Read the instruction byte of the command
* @in param addr: Read the data start character
* @out param rxBuf: Read buffer
* @in param length: need read length
* @return {*}
*/
ft_error_t FQSpi_FlashRead(FQSpi_t *pQspi,
FT_IN u8 cmd,
FT_IN u32 addr,
FT_OUT u8 *rxBuf,
u32 length)
{
FQSpi_Config_t *pConfig = NULL;
FQSpi_RdCfgReg_t rdCfgReg;
Ft_assertNonvoid(pQspi != NULL);
Ft_assertNonvoid(pQspi->isReady == FT_COMPONENT_IS_READLY);
pConfig = &pQspi->config;
if ((NULL == rxBuf) || (0 == length))
{
return FQSPI_FAILURE;
}
rdCfgReg.data = 0;
rdCfgReg.val.rdCmd = cmd;
rdCfgReg.val.dBuffer = 1;
rdCfgReg.val.rdAddrSel = pConfig->addrMode;
rdCfgReg.val.rdSckSel = pConfig->clkDiv;
rdCfgReg.val.rdTransfer = pConfig->transMode;
Ft_out32(pConfig->baseAddress + FT_REG_QSPI_RD_CFG_OFFSET, rdCfgReg.data);
memcpy(rxBuf, (char *)(addr), length);
return FQSPI_SUCCESS;
}
/**
* @name: FQSpi_FlashWrite
* @msg: Writes one page into flash,changing bits from 1 to 0
* @in param pQspi:
* @in param cmd: write the instruction byte of the command
* @in param addr: write the data start character
* @in param txBuf: write buffer
* @in param length: need write length
* @return {*}
*/
ft_error_t FQSpi_FlashWrite(FQSpi_t *pQspi,
FT_IN u8 cmd,
FT_IN u32 addr,
FT_IN u8 *txBuf,
u32 length)
{
FQSpi_Config_t *pConfig = NULL;
FQSpi_WrCfgReg_t wrCfgReg;
u32 index = 0;
u32 val = 0;
u32 *pu32Buf = NULL;
Ft_assertNonvoid(pQspi != NULL);
Ft_assertNonvoid(pQspi->isReady == FT_COMPONENT_IS_READLY);
pConfig = &pQspi->config;
if ((NULL == txBuf) || (0 == length))
{
return FQSPI_FAILURE;
}
pu32Buf = (u32 *)txBuf;
wrCfgReg.data = 0;
wrCfgReg.val.wrCmd = cmd;
wrCfgReg.val.wrWait = 1;
wrCfgReg.val.wrSckSel = pConfig->clkDiv;
wrCfgReg.val.wrAddrsel = pConfig->addrMode;
wrCfgReg.val.wrTransfer = pConfig->transMode;
wrCfgReg.val.wrMode = 1;
Ft_out32(pConfig->baseAddress + FT_REG_QSPI_WR_CFG_OFFSET, wrCfgReg.data);
while (length)
{
if (length >= 4)
{
Ft_out32(addr + index, pu32Buf[index / 4]);
length -= 4;
index += 4;
}
else
{
if (1 == length)
{
val = txBuf[index] | 0xFFFFFF00;
}
else if (2 == length)
{
val = txBuf[index] | (txBuf[index + 1] << 8) | 0xFFFF0000;
}
else
{
val = txBuf[index] | (txBuf[index + 1] << 8) | (txBuf[index + 2] << 8) | 0xFF000000;
}
Ft_out32(addr + index, val);
length = 0;
}
}
Ft_out32(pConfig->baseAddress + FT_REG_QSPI_FLUSH_OFFSET, 1);
return FQSPI_SUCCESS;
}
/**
* @name: FQSpi_FlashRegSet
* @msg: Set registers of flash
* @in param cmd: Command byte
* @in param writebuf: write buffer
* @in param length: need write length
* @return {*}
*/
ft_error_t FQSpi_FlashRegSet(FQSpi_t *pQspi,
FT_IN u8 cmd,
FT_IN u8 *writebuf,
u32 length)
{
FQSpi_Config_t *pConfig = NULL;
FQSpi_CmdPortReg_t cmdPortReg;
Ft_assertNonvoid(pQspi != NULL);
Ft_assertNonvoid(pQspi->isReady == FT_COMPONENT_IS_READLY);
pConfig = &pQspi->config;
cmdPortReg.data = 0;
cmdPortReg.val.cmd = cmd;
cmdPortReg.val.wait = 1;
cmdPortReg.val.sckSel = pConfig->clkDiv;
cmdPortReg.val.transfer = pConfig->transMode;
cmdPortReg.val.cs = pConfig->channel;
if (length == 0)
{
Ft_out32(pConfig->baseAddress + FT_REG_QSPI_CMD_PORT_OFFSET, cmdPortReg.data);
Ft_out32(pConfig->baseAddress + FT_REG_QSPI_LD_PORT_OFFSET, 1);
}
else
{
cmdPortReg.val.dataTransfer = 1;
cmdPortReg.val.rwMum = length;
Ft_out32(pConfig->baseAddress + FT_REG_QSPI_CMD_PORT_OFFSET, cmdPortReg.data);
FQSpi_MemcpyToReg(pQspi, writebuf, length);
}
return FQSPI_SUCCESS;
}
ft_error_t FQSpi_FlashRegSetWithaddr(FQSpi_t *pQspi,
FT_IN u8 cmd,
FT_IN u32 addr,
FT_IN u8 *writebuf,
u32 length)
{
FQSpi_Config_t *pConfig = NULL;
FQSpi_CmdPortReg_t cmdPortReg;
Ft_assertNonvoid(pQspi != NULL);
Ft_assertNonvoid(pQspi->isReady == FT_COMPONENT_IS_READLY);
pConfig = &pQspi->config;
cmdPortReg.data = 0;
cmdPortReg.val.cmd = cmd;
cmdPortReg.val.wait = 1;
cmdPortReg.val.sckSel = pConfig->clkDiv;
cmdPortReg.val.transfer = pConfig->transMode;
cmdPortReg.val.cs = pConfig->channel;
cmdPortReg.val.cmdAddr = 1;
cmdPortReg.val.addrSel = pConfig->addrMode;
Ft_out32(pConfig->baseAddress + FT_REG_QSPI_ADDR_PORT_OFFSET, addr);
if (length == 0)
{
Ft_out32(pConfig->baseAddress + FT_REG_QSPI_CMD_PORT_OFFSET, cmdPortReg.data);
Ft_out32(pConfig->baseAddress + FT_REG_QSPI_LD_PORT_OFFSET, 0);
}
else
{
cmdPortReg.val.dataTransfer = 1;
cmdPortReg.val.rwMum = length;
Ft_out32(pConfig->baseAddress + FT_REG_QSPI_CMD_PORT_OFFSET, cmdPortReg.data);
FQSpi_MemcpyToReg(pQspi, writebuf, length);
}
return FQSPI_SUCCESS;
}
ft_error_t FQSpi_FlashRegGet(FQSpi_t *pQspi,
FT_IN u8 cmd,
u8 *readbuf,
u32 length)
{
FQSpi_Config_t *pConfig = NULL;
FQSpi_CmdPortReg_t cmdPortReg;
Ft_assertNonvoid(pQspi != NULL);
Ft_assertNonvoid(pQspi->isReady == FT_COMPONENT_IS_READLY);
pConfig = &pQspi->config;
cmdPortReg.data = 0;
cmdPortReg.val.cmd = cmd;
cmdPortReg.val.wait = 1;
cmdPortReg.val.sckSel = pConfig->clkDiv;
cmdPortReg.val.transfer = pConfig->transMode;
cmdPortReg.val.cs = pConfig->channel;
cmdPortReg.val.dataTransfer = 1;
cmdPortReg.val.pBuffer = 1;
Ft_out32(pConfig->baseAddress + FT_REG_QSPI_CMD_PORT_OFFSET, cmdPortReg.data);
FQSpi_MemcpyFromReg(pQspi, readbuf, length);
return FQSPI_SUCCESS;
}
ft_error_t FQSpi_FlashRegGetWithAddr(FQSpi_t *pQspi,
FT_IN u8 cmd,
FT_IN u32 addr,
FT_IN u32 dummyCycle,
u8 *readbuf,
u32 length)
{
FQSpi_Config_t *pConfig = NULL;
FQSpi_CmdPortReg_t cmdPortReg;
Ft_assertNonvoid(pQspi != NULL);
Ft_assertNonvoid(pQspi->isReady == FT_COMPONENT_IS_READLY);
pConfig = &pQspi->config;
cmdPortReg.data = 0;
cmdPortReg.val.cmd = cmd;
cmdPortReg.val.wait = 1;
cmdPortReg.val.sckSel = pConfig->clkDiv;
cmdPortReg.val.transfer = pConfig->transMode;
cmdPortReg.val.cs = pConfig->channel;
cmdPortReg.val.dataTransfer = 1;
cmdPortReg.val.pBuffer = 1;
cmdPortReg.val.cmdAddr = 1;
cmdPortReg.val.addrSel = pConfig->addrMode;
cmdPortReg.val.latency = 1;
cmdPortReg.val.dummy = dummyCycle - 1;
Ft_out32(pConfig->baseAddress + FT_REG_QSPI_ADDR_PORT_OFFSET, addr);
Ft_out32(pConfig->baseAddress + FT_REG_QSPI_CMD_PORT_OFFSET, cmdPortReg.data);
FQSpi_MemcpyFromReg(pQspi, readbuf, length);
return FQSPI_SUCCESS;
}
ft_error_t FQSpi_Write(FQSpi_t *pQspi, struct FQSpi_DataPack *pDataPack)
{
FQSpi_Config_t *pConfig = NULL;
FQSpi_WrCfgReg_t wrCfgReg;
u32 length;
u32 index = 0;
u32 val = 0;
const u32 *pu32Buf = NULL;
Ft_assertNonvoid(pQspi != NULL);
Ft_assertNonvoid(pQspi->isReady == FT_COMPONENT_IS_READLY);
pConfig = &pQspi->config;
if ((FQSPI_DATA_ADDRESS_3BYTE_MASK | FQSPI_DATA_ADDRESS_4BYTE_MASK) == (pDataPack->flags & (FQSPI_DATA_ADDRESS_3BYTE_MASK | FQSPI_DATA_ADDRESS_4BYTE_MASK)))
{
FTQSPI_DEBUG_E(" Two addresses are not allowed at the same time ");
return FQSPI_FAILURE;
}
if (0 == (pDataPack->flags & (FQSPI_DATA_ADDRESS_3BYTE_MASK | FQSPI_DATA_ADDRESS_4BYTE_MASK)))
{
FTQSPI_DEBUG_E(" There is no address configuration ");
return FQSPI_FAILURE;
}
if (NULL == pDataPack->txBuf)
{
FTQSPI_DEBUG_E("pDataPack->txBuf is null");
return FQSPI_FAILURE;
}
pu32Buf = (const u32 *)pDataPack->txBuf;
wrCfgReg.data = 0;
if (FQSPI_DATA_ADDRESS_3BYTE_MASK == (pDataPack->flags & FQSPI_DATA_ADDRESS_3BYTE_MASK))
{
wrCfgReg.val.wrAddrsel = FT_QSPI_ADDR_SEL_3;
}
else if (FQSPI_DATA_ADDRESS_4BYTE_MASK == (pDataPack->flags & FQSPI_DATA_ADDRESS_4BYTE_MASK))
{
wrCfgReg.val.wrAddrsel = FT_QSPI_ADDR_SEL_4;
}
wrCfgReg.val.wrCmd = pDataPack->cmd;
wrCfgReg.val.wrWait = 1;
wrCfgReg.val.wrSckSel = pConfig->clkDiv;
wrCfgReg.val.wrTransfer = pConfig->transMode;
wrCfgReg.val.wrMode = 1;
length = pDataPack->length;
Ft_out32(pConfig->baseAddress + FT_REG_QSPI_WR_CFG_OFFSET, wrCfgReg.data);
while (length)
{
if (length >= 4)
{
Ft_out32(pDataPack->addr + index, pu32Buf[index / 4]);
length -= 4;
index += 4;
}
else
{
if (1 == length)
{
val = pDataPack->txBuf[index] | 0xFFFFFF00;
}
else if (2 == length)
{
val = pDataPack->txBuf[index] | (pDataPack->txBuf[index + 1] << 8) | 0xFFFF0000;
}
else
{
val = pDataPack->txBuf[index] | (pDataPack->txBuf[index + 1] << 8) | (pDataPack->txBuf[index + 2] << 8) | 0xFF000000;
}
FTQSPI_DEBUG_I("val is 0x%x", val);
Ft_out32(pDataPack->addr + index, val);
length = 0;
}
}
Ft_out32(pConfig->baseAddress + FT_REG_QSPI_FLUSH_OFFSET, 1);
return FQSPI_SUCCESS;
}
ft_error_t FQSpi_Read(FQSpi_t *pQspi, struct FQSpi_DataPack *pDataPack)
{
FQSpi_Config_t *pConfig = NULL;
FQSpi_RdCfgReg_t rdCfgReg;
Ft_assertNonvoid(pQspi != NULL);
Ft_assertNonvoid(pQspi->isReady == FT_COMPONENT_IS_READLY);
pConfig = &pQspi->config;
if ((FQSPI_DATA_ADDRESS_3BYTE_MASK | FQSPI_DATA_ADDRESS_4BYTE_MASK) == (pDataPack->flags & (FQSPI_DATA_ADDRESS_3BYTE_MASK | FQSPI_DATA_ADDRESS_4BYTE_MASK)))
{
FTQSPI_DEBUG_E(" Two addresses are not allowed at the same time ");
return FQSPI_FAILURE;
}
if (0 == (pDataPack->flags & (FQSPI_DATA_ADDRESS_3BYTE_MASK | FQSPI_DATA_ADDRESS_4BYTE_MASK)))
{
FTQSPI_DEBUG_E(" There is no address configuration ");
return FQSPI_FAILURE;
}
if (NULL == pDataPack->rxBuf)
{
FTQSPI_DEBUG_E("pDataPack->rxBuf is null");
return FQSPI_FAILURE;
}
rdCfgReg.data = 0;
if (FQSPI_DATA_NEED_DUMMY_MASK == (pDataPack->flags & FQSPI_DATA_NEED_DUMMY_MASK))
{
rdCfgReg.val.rdLatency = 1;
rdCfgReg.val.dummy = pDataPack->dummyCycle - 1;
}
if (FQSPI_DATA_ADDRESS_3BYTE_MASK == (pDataPack->flags & FQSPI_DATA_ADDRESS_3BYTE_MASK))
{
rdCfgReg.val.rdAddrSel = FT_QSPI_ADDR_SEL_3;
}
else if (FQSPI_DATA_ADDRESS_4BYTE_MASK == (pDataPack->flags & FQSPI_DATA_ADDRESS_4BYTE_MASK))
{
rdCfgReg.val.rdAddrSel = FT_QSPI_ADDR_SEL_4;
}
rdCfgReg.val.rdCmd = pDataPack->cmd;
rdCfgReg.val.dBuffer = 1;
rdCfgReg.val.rdSckSel = pConfig->clkDiv;
rdCfgReg.val.rdTransfer = pConfig->transMode;
Ft_out32(pConfig->baseAddress + FT_REG_QSPI_RD_CFG_OFFSET, rdCfgReg.data);
memcpy(pDataPack->rxBuf, (char *)(pDataPack->addr), pDataPack->length);
return FQSPI_SUCCESS;
}
ft_error_t
FQSpi_CmdOperation(FQSpi_t *pQspi, struct FQSpi_CmdPack *pCmdPack)
{
FQSpi_Config_t *pConfig = NULL;
FQSpi_CmdPortReg_t cmdPortReg;
Ft_assertNonvoid(pQspi != NULL);
Ft_assertNonvoid(pQspi->isReady == FT_COMPONENT_IS_READLY);
pConfig = &pQspi->config;
if ((FQSPI_CMD_ADDRESS_3BYTE_MASK | FQSPI_CMD_ADDRESS_4BYTE_MASK) == (pCmdPack->flags & (FQSPI_CMD_ADDRESS_3BYTE_MASK | FQSPI_CMD_ADDRESS_4BYTE_MASK)))
{
FTQSPI_DEBUG_E(" Two addresses are not allowed at the same time ");
return FQSPI_FAILURE;
}
cmdPortReg.data = 0;
cmdPortReg.val.cmd = pCmdPack->cmd;
cmdPortReg.val.wait = 1;
cmdPortReg.val.sckSel = pConfig->clkDiv;
cmdPortReg.val.transfer = pConfig->transMode;
cmdPortReg.val.cs = pConfig->channel;
if (FQSPI_CMD_NEED_ADDR_MASK == (pCmdPack->flags & FQSPI_CMD_NEED_ADDR_MASK))
{
// FTQSPI_DEBUG_I(" send addr is 0x%x ", pCmdPack->addr);
cmdPortReg.val.cmdAddr = 1;
Ft_out32(pConfig->baseAddress + FT_REG_QSPI_ADDR_PORT_OFFSET, pCmdPack->addr);
}
if (FQSPI_CMD_NEED_DUMMY_MASK == (pCmdPack->flags & FQSPI_CMD_NEED_DUMMY_MASK))
{
cmdPortReg.val.latency = 1;
cmdPortReg.val.dummy = pCmdPack->dummyCycle - 1;
}
if (FQSPI_CMD_ADDRESS_3BYTE_MASK == (pCmdPack->flags & FQSPI_CMD_ADDRESS_3BYTE_MASK))
{
cmdPortReg.val.addrSel = FT_QSPI_ADDR_SEL_3;
}
else if (FQSPI_CMD_ADDRESS_4BYTE_MASK == (pCmdPack->flags & FQSPI_CMD_ADDRESS_4BYTE_MASK))
{
cmdPortReg.val.addrSel = FT_QSPI_ADDR_SEL_4;
}
if (FQSPI_CMD_NEED_SET_MASK == (pCmdPack->flags & (FQSPI_CMD_NEED_SET_MASK)))
{
cmdPortReg.val.dataTransfer = 1;
cmdPortReg.val.rwMum = pCmdPack->length;
Ft_out32(pConfig->baseAddress + FT_REG_QSPI_CMD_PORT_OFFSET, cmdPortReg.data);
FQSpi_MemcpyToReg(pQspi, pCmdPack->txBuf, pCmdPack->length);
}
else if (FQSPI_CMD_NEED_GET_MASK == (pCmdPack->flags & (FQSPI_CMD_NEED_GET_MASK)))
{
cmdPortReg.val.dataTransfer = 1;
cmdPortReg.val.pBuffer = 1;
Ft_out32(pConfig->baseAddress + FT_REG_QSPI_CMD_PORT_OFFSET, cmdPortReg.data);
FQSpi_MemcpyFromReg(pQspi, pCmdPack->rxBuf, pCmdPack->length);
}
else
{
Ft_out32(pConfig->baseAddress + FT_REG_QSPI_CMD_PORT_OFFSET, cmdPortReg.data);
if (FQSPI_CMD_NEED_ADDR_MASK == (pCmdPack->flags & FQSPI_CMD_NEED_ADDR_MASK))
{
Ft_out32(pConfig->baseAddress + FT_REG_QSPI_LD_PORT_OFFSET, 0);
}
else
{
Ft_out32(pConfig->baseAddress + FT_REG_QSPI_LD_PORT_OFFSET, 1);
}
}
return FQSPI_SUCCESS;
}

View File

@ -0,0 +1,184 @@
/*
 * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
 *
 * SPDX-License-Identifier: Apache-2.0.
*
* @Date: 2021-04-05 21:31:10
* @LastEditTime: 2021-04-05 21:31:10
* @Description:  Description of file
* @Modify History:
* * * Ver   Who        Date         Changes
* * ----- ------     --------    --------------------------------------
* * v1.0 hh 2021-04-05 init
*/
#ifndef FT_QSPI_H
#define FT_QSPI_H
#ifdef __cplusplus
extern "C"
{
#endif
#include "ft_types.h"
#include "ft_error_code.h"
#define FQSPI_SUCCESS FST_SUCCESS /* SUCCESS */
#define FQSPI_FAILURE FT_MAKE_ERRCODE(errQspi, errBspGeneral, FST_FAILURE) /* Normal */
#define FQSPI_TIMEOUT FT_MAKE_ERRCODE(errQspi, errBspGeneral, FST_TIMEOUT) /* Timeout */
#define FQSPI_EILSEQ FT_MAKE_ERRCODE(errQspi, errBspGeneral, FST_EILSEQ) /* Illegal byte sequence. */
#define FQSPI_INVALID_PARAM FT_MAKE_ERRCODE(errQspi, errBspGeneral, FST_INVALID_PARAM) /* Invalid param. */
/* qspi bsp command instruction operation */
#define FQSPI_CMD_NEED_ADDR_MASK 0x1U
#define FQSPI_CMD_NEED_DUMMY_MASK 0x2U
#define FQSPI_CMD_NEED_GET_MASK 0x4U
#define FQSPI_CMD_NEED_SET_MASK 0x08U
#define FQSPI_CMD_ADDRESS_3BYTE_MASK 0x10U
#define FQSPI_CMD_ADDRESS_4BYTE_MASK 0x20U
/* qspi cmd of transfer operation */
#define FQSPI_DATA_NEED_DUMMY_MASK 0x1U
#define FQSPI_DATA_ADDRESS_3BYTE_MASK 0x2U
#define FQSPI_DATA_ADDRESS_4BYTE_MASK 0x4U
#define FQSPI_FLASH_CMD_WRR 0x01 /* Write status register */
#define FQSPI_FLASH_CMD_PP 0x02 /* Page program */
#define FQSPI_FLASH_CMD_READ 0x03 /* Normal read data bytes */
#define FQSPI_FLASH_CMD_WRDI 0x04 /* Write disable */
#define FQSPI_FLASH_CMD_RDSR1 0x05 /* Read status register */
#define FQSPI_FLASH_CMD_WREN 0x06 /* Write enable */
#define FQSPI_FLASH_CMD_RDSR2 0x07 /* Read status register */
#define FQSPI_FLASH_CMD_FAST_READ 0x0B /* Fast read data bytes */
#define FQSPI_FLASH_CMD_4FAST_READ 0x0C /* Fast read data bytes */
#define FQSPI_FLASH_CMD_4PP 0x12 /* Page program */
#define FQSPI_FLASH_CMD_4READ 0x13 /* Normal read data bytes */
#define FQSPI_FLASH_CMD_P4E 0x20 /* Erase 4kb sector */
#define FQSPI_FLASH_CMD_4P4E 0x21 /* Erase 4kb sector */
#define FQSPI_FLASH_CMD_QPP 0x32 /* Quad Page program */
#define FQSPI_FLASH_CMD_4QPP 0x34 /* Quad Page program */
#define FQSPI_FLASH_CMD_RDCR 0x35 /* Read config register */
#define FQSPI_FLASH_CMD_BE 0x60 /* Bulk erase */
#define FQSPI_FLASH_CMD_RDAR 0x65 /* Read Any Register */
#define FQSPI_FLASH_CMD_QOR 0x6B /* Quad read data bytes */
#define FQSPI_FLASH_CMD_4QOR 0x6C /* Quad read data bytes */
#define FQSPI_FLASH_CMD_WRAR 0x71 /* Write Any Register */
#define FQSPI_FLASH_CMD_RDID 0x9F /* Read JEDEC ID */
#define FQSPI_FLASH_CMD_4BAM 0xB7 /* Enter 4 Bytes Mode */
#define FQSPI_FLASH_CMD_4BE 0xC7 /* Bulk erase */
#define FQSPI_FLASH_CMD_SE 0xD8 /* Sector erase */
#define FQSPI_FLASH_CMD_4SE 0xDC /* Sector erase */
#define FQSPI_FLASH_CMD_4BEX 0xE9 /* Exit 4 Bytes Mode */
#define FQSPI_FLASH_CMD_QIOR 0xEB /* Quad read data bytes */
#define FQSPI_FLASH_CMD_4QIOR 0xEC /* Quad read data bytes */
#define FQSPI_FLASH_DISCOVERABLE_PARAMETER 0x5a
#define FQSPI_CMD_ENABLE_RESET 0x66
#define FQSPI_CMD_RESET 0x99
struct FQSpi_DataPack
{
u32 flags; /* Follow qspi cmd of transfer operation */
u32 cmd; /* Command instruction */
u32 addr; /* Flash address */
u32 dummyCycle; /* dummy Cycle */
const u8 *txBuf;
u8 *rxBuf; /* Need send or read buffer */
u32 length; /* Buffer length */
};
struct FQSpi_CmdPack
{
u32 flags; /* Follow qspi bsp command instruction operation */
u32 cmd; /* Command instruction */
u32 addr; /* Command address */
u32 dummyCycle; /* dummy Cycle */
const u8 *txBuf;
u8 *rxBuf; /* Need send or read buffer */
u32 length; /* Buffer length */
};
typedef struct
{
u32 instanceId; /* Id of device */
uintptr_t baseAddress; /* Base address of qspi */
u32 transMode; /* Transfer mode */
u32 capacity; /* Flash capacity */
u32 addrMode; /**/
u32 clkDiv;
u32 qspiDevNum; /*Qspi device number */
u32 channel; /* Cs number */
u32 bitWidth; /* Transfer unit width */
} FQSpi_Config_t;
typedef struct
{
FQSpi_Config_t config;
u32 isReady; /**< Device is initialized and ready */
} FQSpi_t;
/**
* @name: FQSpi_LookupConfig
* @msg: FQSpi_LookupConfig returns a reference FQSpi_Config_t structure based on the
* unique device id.
* @in param {u32} instanceId : unique device
* @return {FQSpi_Config_t} FQSpi_Config_t is a reference to a config record in the configuration
* table (in qspi_g.c) corresponding to <i>instanceId</i>, or NULL if no match is found.
*/
FQSpi_Config_t *FQSpi_LookupConfig(u32 instanceId);
/**
* @name: FQSpi_CfgInitialize
* @msg: This function intializes the configuration for the qspi instance
* @in param {FQSpi_t *} pQspi: A pointer to the qspi instance
* @in param {FQSpi_Config_t *} pConfig: A pointer to the qspi instance config record
* @return {ft_error_t}
*/
ft_error_t FQSpi_CfgInitialize(FQSpi_t *pQspi, FQSpi_Config_t *pConfig);
/**
* @name: FQSpi_CmdOperation
* @msg: This function send command instruction by the struct FQSpi_CmdPack
* @in param {FQSpi_t *} pQspi: A pointer to the qspi instance
* @in param {struct FQSpi_CmdPack *} pCmdPack: Need to send command instruction package
* @return {ft_error_t}
*/
ft_error_t FQSpi_CmdOperation(FQSpi_t *pQspi, struct FQSpi_CmdPack *pCmdPack);
/**
* @name: FQSpi_Read
* @msg: This function reads flash data from a specific address by {struct FQSpi_DataPack}
* @in param {FQSpi_t *} pQspi: A pointer to the qspi instance
* @in param {struct FQSpi_DataPack *} pDataPack: Need to read data package
* @return {ft_error_t}
*/
ft_error_t FQSpi_Read(FQSpi_t *pQspi, struct FQSpi_DataPack *pDataPack);
/**
* @name: FQSpi_Write
* @msg: This function writes data from a specific address by {struct FQSpi_DataPack}
* @in param {FQSpi_t *} pQspi: A pointer to the qspi instance
* @in param {struct FQSpi_DataPack *} pDataPack: Need to read data package
* @return {ft_error_t}
*/
ft_error_t FQSpi_Write(FQSpi_t *pQspi, struct FQSpi_DataPack *pDataPack);
/**
* @name: FQSpi_FlashRegSet
* @msg: This function sends command instruction with specific parameters
* @in param {FQSpi_t *} pQspi: A pointer to the qspi instance
* @in param {FT_IN u8} cmd: Command instruction
* @in param {FT_IN u8 *} writebuf: Data that needs to be sent through command instruction registers
* @in param {u32} length: Data length
* @return {ft_error_t}
*/
ft_error_t FQSpi_FlashRegSet(FQSpi_t *pQspi,
FT_IN u8 cmd,
FT_IN u8 *writebuf,
u32 length);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,26 @@
/*
 * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
 *
 * SPDX-License-Identifier: Apache-2.0.
*
* @Date: 2021-04-07 11:31:12
* @LastEditTime: 2021-04-07 11:31:13
* @Description:  Description of file
* @Modify History:
* * * Ver   Who        Date         Changes
* * ----- ------     --------    --------------------------------------
* * v1.0 hh 2021-04-07 init
*/
#include "ft_qspi.h"
#include "ft_parameters.h"
FQSpi_Config_t FqSpi_ConfigTable[FT_QSPI_NUM] = {
{.instanceId = FT_QSPI_INSTANCE, /* Id of device */
.baseAddress = FT_QSPI_BASEADDR, /* Base address of qspi */
.transMode = FT_QSPI_TRANSFER_1_1_1, /* Transfer mode */
.capacity = FT_QSPI_FLASH_CAP_32MB, /* Flash capacity */
.addrMode = FT_QSPI_ADDR_SEL_3, /**/
.clkDiv = FT_QSPI_SCK_DIV_128,
.qspiDevNum = 1,
.channel = 0,
.bitWidth = 8}};

View File

@ -0,0 +1,25 @@
/*
 * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
 *
 * SPDX-License-Identifier: Apache-2.0.
*
* @Date: 2021-04-02 18:32:42
* @LastEditTime: 2021-04-02 18:32:43
* @Description:  Description of file
* @Modify History:
* * * Ver   Who        Date         Changes
* * ----- ------     --------    --------------------------------------
*/
#include "qspi_hw.h"
#include "ft_qspi.h"
#include "ft_assert.h"
#include "ft_io.h"
void FQSpi_Reset(FQSpi_t *pQspi)
{
FQSpi_Config_t *pConfig = NULL;
Ft_assertVoid(pQspi != NULL);
pConfig = &pQspi->config;
Ft_out32(pConfig->baseAddress + FT_REG_QSPI_CAP_OFFSET,
FT_REG_QSPI_CAP_FLASH_NUM(pConfig->qspiDevNum) | FT_REG_QSPI_CAP_FLASH_CAP(pConfig->capacity));
}

View File

@ -0,0 +1,199 @@
/*
 * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
 *
 * SPDX-License-Identifier: Apache-2.0.
*
* @Date: 2021-04-02 18:32:54
* @LastEditTime: 2021-05-24 14:33:45
* @Description:  Description of file
*
* @Modify History:
* * * Ver   Who        Date         Changes
* * ----- ------     --------    --------------------------------------
*/
#ifndef QSPI_HW_H
#define QSPI_HW_H
#ifdef __cplusplus
extern "C"
{
#endif
#include "ft_qspi.h"
#include "ft_types.h"
/* register definition */
#define FT_REG_QSPI_CAP_OFFSET (0x00) /* Flash capacity setting register */
#define FT_REG_QSPI_RD_CFG_OFFSET (0x04) /* Address access reads configuration registers */
#define FT_REG_QSPI_WR_CFG_OFFSET (0x08) /* Write buffer flush register */
#define FT_REG_QSPI_FLUSH_OFFSET (0x0C) /* Write buffer flush register */
#define FT_REG_QSPI_CMD_PORT_OFFSET (0x10) /* Command port register */
#define FT_REG_QSPI_ADDR_PORT_OFFSET (0x14) /* Address port register */
#define FT_REG_QSPI_HD_PORT_OFFSET (0x18) /* Upper bit port register */
#define FT_REG_QSPI_LD_PORT_OFFSET (0x1C) /* low bit port register */
#define FT_REG_QSPI_FUN_SET_OFFSET (0x20) /* CS setting register */
#define FT_REG_QSPI_WIP_RD_OFFSET (0x24) /* WIP reads the Settings register */
#define FT_REG_QSPI_WP_OFFSET (0x28) /* WP register */
#define FT_REG_QSPI_MODE_OFFSET (0x2C) /* Mode setting register */
/*QSPI_CAP*/
#define FT_REG_QSPI_CAP_FLASH_NUM(data) ((data) << 3) /* Flash number */
#define FT_REG_QSPI_CAP_FLASH_CAP(data) ((data) << 0) /* The flash capacity */
/* RD_CFG */
#define FT_RD_CFG_CMD(data) ((data) << 24) /* Read Command */
#define FT_RD_CFG_THROUGH(data) ((data) << 23) /* The programming flag in the status register */
#define FT_RD_CFG_TRANSFER(data) ((data) << 20) /* */
#define FT_RD_CFG_ADDR_SEL(data) ((data) << 19) /* */
#define FT_RD_CFG_LATENCY(data) ((data) << 18) /* */
#define FT_RD_CFG_MODE_BYTE(data) ((data) << 17) /* */
#define FT_RD_CFG_CMD_SIGN(data) ((data) << 9) /* */
#define FT_RD_CFG_DUMMY(data) ((data) << 4) /* */
#define FT_RD_CFG_D_BUFFER(data) ((data) << 3) /* */
#define FT_RD_CFG_SCK_SEL(data) ((data) << 0) /* */
/*QSPI_WR_CFG*/
#define FT_WR_CFG_CMD(data) ((data) << 24)
#define FT_WR_CFG_WAIT(data) ((data) << 9)
#define FT_WR_CFG_THROUGH(data) ((data) << 8)
#define FT_WR_CFG_TRANSFER(data) ((data) << 5)
#define FT_WR_CFG_ADDRSEL(data) ((data) << 4)
#define FT_WR_CFG_MODE(data) ((data) << 3)
#define FT_WR_CFG_SCK_SEL(data) ((data) << 0)
/*QSPI_CMD_PORT*/
#define FT_CMD_PORT_CMD(data) ((data) << 24)
#define FT_CMD_PORT_WAIT(data) ((data) << 22)
#define FT_CMD_PORT_THROUGH(data) ((data) << 21)
#define FT_CMD_PORT_CS(data) ((data) << 19)
#define FT_CMD_PORT_TRANSFER(data) ((data) << 16)
#define FT_CMD_PORT_ADDR(data) ((data) << 15)
#define FT_CMD_PORT_LATENCY(data) ((data) << 14)
#define FT_CMD_PORT_DATA_TRANS(data) ((data) << 13)
#define FT_CMD_PORT_ADDR_SEL(data) ((data) << 12)
#define FT_CMD_PORT_DUMMY(data) ((data) << 7)
#define FT_CMD_PORT_P_BUFFER(data) ((data) << 6)
#define FT_CMD_PORT_RW_NUM(data) ((data) << 3)
#define FT_CMD_PORT_CLK_SEL(data) ((data) << 0)
/*QSPI_FUN_SET*/
#define FT_FUN_SET_CS_HOLD(data) ((data) << 24)
#define FT_FUN_SET_CS_SETUP(data) ((data) << 16)
#define FT_FUN_SET_CS_DELAY(data) ((data) << 0)
/*QSPI_WIP_RD*/
#define FT_WIP_RD_CMD(data) ((data) << 24)
#define FT_WIP_RD_TRANSFER(data) ((data) << 3)
#define FT_WIP_RD_SCK_SEL(data) ((data) << 0)
/*QSPI_WP*/
#define FT_WP_EN(data) ((data) << 17)
#define FT_WP_WP(data) ((data) << 16)
#define FT_WP_HOLD(data) ((data) << 8)
#define FT_WP_SETUP(data) ((data) << 0)
/*QSPI_MODE*/
#define FT_MODE_VALID(data) ((data) << 8)
#define FT_MODE_MODE(data) ((data) << 0)
#define FT_QSPI_FLASH_CAP_4MB 0
#define FT_QSPI_FLASH_CAP_8MB 1
#define FT_QSPI_FLASH_CAP_16MB 2
#define FT_QSPI_FLASH_CAP_32MB 3
#define FT_QSPI_FLASH_CAP_64MB 4
#define FT_QSPI_FLASH_CAP_128MB 5
#define FT_QSPI_FLASH_CAP_256MB 6
#define FT_QSPI_ADDR_SEL_3 0
#define FT_QSPI_ADDR_SEL_4 1
#define FT_QSPI_SCK_DIV_128 0
#define FT_QSPI_SCK_DIV_2 1
#define FT_QSPI_SCK_DIV_4 2
#define FT_QSPI_SCK_DIV_8 3
#define FT_QSPI_SCK_DIV_16 4
#define FT_QSPI_SCK_DIV_32 5
#define FT_QSPI_SCK_DIV_64 6
#define FT_QSPI_TRANSFER_1_1_1 0
#define FT_QSPI_TRANSFER_1_1_2 1
#define FT_QSPI_TRANSFER_1_1_4 2
#define FT_QSPI_TRANSFER_1_2_2 3
#define FT_QSPI_TRANSFER_1_4_4 4
#define FT_QSPI_TRANSFER_2_2_2 5
#define FT_QSPI_TRANSFER_4_4_4 6
/* typedefs */
/*QSPI_RD_CFG*/
typedef union
{
u32 data;
struct
{
u32 rdSckSel : 3; /* 2:0 */
u32 dBuffer : 1; /* 3 */
u32 dummy : 5; /* 8:4 */
u32 cmdSign : 8; /* 16:9 */
u32 modeByte : 1; /* 17 */
u32 rdLatency : 1; /* 18 */
u32 rdAddrSel : 1; /* 19 */
u32 rdTransfer : 3; /* 22:20 */
u32 rdThrough : 1; /* 23 */
u32 rdCmd : 8; /* 31:24 */
} val;
} FQSpi_RdCfgReg_t;
/*QSPI_WR_CFG*/
typedef union
{
u32 data;
struct
{
u32 wrSckSel : 3; /* 2:0 */
u32 wrMode : 1; /* 3 */
u32 wrAddrsel : 1; /* 4 */
u32 wrTransfer : 3; /* 7:5 */
u32 wrThrough : 1; /* 8 */
u32 wrWait : 1; /* 9 */
u32 wrRes : 14; /* 23:10 */
u32 wrCmd : 8; /* 31:24 */
} val;
} FQSpi_WrCfgReg_t;
/*QSPI_CMD_PORT*/
typedef union
{
u32 data;
struct
{
u32 sckSel : 3; /* 2:0 */
u32 rwMum : 3; /* 5:3 */
u32 pBuffer : 1; /* 6 */
u32 dummy : 5; /* 11:7 */
u32 addrSel : 1; /* 12 */
u32 dataTransfer : 1; /* 13 */
u32 latency : 1; /* 14 */
u32 cmdAddr : 1; /* 15 */
u32 transfer : 3; /* 18:16 */
u32 cs : 2; /* 20:19 */
u32 through : 1; /* 21 */
u32 wait : 1; /* 22 */
u32 res : 1; /* 23 */
u32 cmd : 8; /* 31:24 */
} val;
} FQSpi_CmdPortReg_t;
/**
* @name: FQSpi_Reset
* @msg: This routine performs the QSPI controller initialization.
* @in param: pQspi
* @return {*}
*/
void FQSpi_Reset(FQSpi_t *pQspi);
#ifdef __cplusplus
}
#endif
#endif // !

View File

@ -0,0 +1,34 @@
/*
 * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
 *
 * SPDX-License-Identifier: Apache-2.0.
*
* @Date: 2021-04-07 13:22:01
* @LastEditTime: 2021-04-07 13:22:01
* @Description:  Description of file
* @Modify History:
* * * Ver   Who        Date         Changes
* * ----- ------     --------    --------------------------------------
*/
#include "ft_qspi.h"
#include "ft_parameters.h"
extern FQSpi_Config_t FqSpi_ConfigTable[FT_QSPI_NUM];
FQSpi_Config_t *FQSpi_LookupConfig(u32 instanceId)
{
FQSpi_Config_t *pFQSpi_Config_t = NULL;
u32 Index;
for (Index = 0; Index < (u32)FT_GMAC_INSTANCES_NUM; Index++)
{
if (FqSpi_ConfigTable[Index].instanceId == instanceId)
{
pFQSpi_Config_t = &FqSpi_ConfigTable[Index];
break;
}
}
return pFQSpi_Config_t;
}

View File

@ -0,0 +1,552 @@
/*
 * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
 *
 * SPDX-License-Identifier: Apache-2.0.
 *
* @Date: 2021-03-31 14:59:20
* @LastEditTime: 2021-05-25 16:49:01
* @Description:  This files is for implemenation of sd ctrl
*
* @Modify History: * * Ver   Who        Date         Changes
* ----- ------     --------    --------------------------------------
*/
#include "ft_parameters.h"
#include "ft_assert.h"
#include "ft_io.h"
#include "ft_sdctrl.h"
#include "ft_sdctrl_hw.h"
#include "ft_debug.h"
#include "ft_printf.h"
#include "ft_trace.h"
#include "ft_cache.h"
#define FT_SD_CTRL_DEBUG_I(format, ...) FT_DEBUG_PRINT_I(FT_SD_CTRL_DEBUG_TAG, format, ##__VA_ARGS__)
#define FT_SD_CTRL_DEBUG_E(format, ...) FT_DEBUG_PRINT_E(FT_SD_CTRL_DEBUG_TAG, format, ##__VA_ARGS__)
#define FT_SD_CTRL_DEBUG_W(format, ...) FT_DEBUG_PRINT_W(FT_SD_CTRL_DEBUG_TAG, format, ##__VA_ARGS__)
void FSdCtrl_ClkFreqSetup(FT_INOUT FtsdCtrl_t *pFtsdCtrl, FT_IN u32 sdClk)
{
FSdCtrl_Config_t *pConfig;
u32 clkDiv;
u32 inputClk;
u32 tmpSdFreq;
u32 workSpeed;
Ft_assertVoid(FT_NULL != pFtsdCtrl);
pConfig = &pFtsdCtrl->config;
inputClk = pConfig->inputClockHz;
/* sd work speed is limit to 25MHz */
workSpeed = (sdClk < SD_CLK_FREQ_25MHZ) ? sdClk : SD_CLK_FREQ_25MHZ;
/* if sd clk freq is valid and is two times greater than io input clk */
if ((SD_CLK_FREQ_400KHZ < workSpeed) && (inputClk > (2 * workSpeed)))
{
clkDiv = (u32)(inputClk / (2 * workSpeed)) - 1;
/* calculte sd freq one more time base on divsor */
tmpSdFreq = (u32)inputClk / (2 * (clkDiv + 1));
/* if calculated sd freq is greater than the real val */
if (tmpSdFreq > workSpeed)
{
clkDiv += 1;
}
}
else
{
clkDiv = SD_FRRQ_DIV_DEFAULT;
}
Ft_out32(pConfig->baseAddress + CLOCK_DIV_REG_OFFSET, clkDiv);
return;
}
ft_error_t FsdCtrl_Init(FT_INOUT FtsdCtrl_t *pFtsdCtrl)
{
FSdCtrl_Config_t *pConfig;
Ft_assertNonvoid(FT_NULL != pFtsdCtrl);
pConfig = &pFtsdCtrl->config;
/* Disable card detection */
Ft_out32(pConfig->baseAddress + SD_SEN_REG_OFFSET, 0);
/* Disable all interrupts */
Ft_out32(pConfig->baseAddress + NORMAL_INT_EN_REG_OFFSET, 0);
Ft_out32(pConfig->baseAddress + ERROR_INT_EN_REG_OFFSET, 0);
Ft_out32(pConfig->baseAddress + BD_ISR_EN_REG_OFFSET, 0);
// Ft_out32(pConfig->baseAddress + NORMAL_INT_EN_REG_OFFSET, NORMAL_INT_EN_ECCRCE);
/* Clear status register */
Ft_out32(pConfig->baseAddress + NORMAL_INT_STATUS_REG, 0);
Ft_out32(pConfig->baseAddress + ERROR_INT_STATUS_REG, 0);
Ft_out32(pConfig->baseAddress + BD_ISR_REG, 0);
/* Set default ctrl register */
Ft_out32(pConfig->baseAddress + CONTROLL_SETTING_REG_OFFSET, 0x0f00);
/* Set default drive and sampling register */
Ft_out32(pConfig->baseAddress + SD_DRV_REG_OFFSET, 0);
Ft_out32(pConfig->baseAddress + SD_SAMP_REG_OFFSET, 0);
/* Configure to default cmd data timeout */
Ft_out32(pConfig->baseAddress + TIMEOUT_CMD_REG_OFFSET, 0xFFFFFFFF);
//FSdCtrl_ClkFreqSetup(pFtsdCtrl, 1);
Ft_out32(pConfig->baseAddress + CLOCK_DIV_REG_OFFSET, SD_FRRQ_DIV_DEFAULT);
Ft_out32(pConfig->baseAddress + SD_SAMP_REG_OFFSET, SD_SAMP_DEFAULT);
pFtsdCtrl->isReady = FT_COMPONENT_IS_READLY;
return FTSDC_SUCCESS;
}
bool_t FSdCtrl_CardDetect(FT_INOUT FtsdCtrl_t *pFtsdCtrl)
{
FSdCtrl_Config_t *pConfig;
u32 status;
Ft_assertBool(FT_NULL != pFtsdCtrl);
pConfig = &pFtsdCtrl->config;
status = Ft_in32(pConfig->baseAddress + STATUS_REG);
/* check card-detection signal */
if (((status)&STATUS_REG_CDSL) == STATUS_REG_CDSL)
{
pConfig->cardDetect = 0;
}
else
{
pConfig->cardDetect = 1;
}
return pConfig->cardDetect;
}
void FSdCtrl_ResetDma(FT_INOUT FtsdCtrl_t *pFtsdCtrl)
{
FSdCtrl_Config_t *pConfig;
Ft_assertVoid(FT_NULL != pFtsdCtrl);
pConfig = &pFtsdCtrl->config;
Ft_setBit32((UINTPTR)(pConfig->baseAddress + SOFTWARE_RESET_REG_OFFSET), SOFTWARE_RESET_BDRST);
Ft_clearBit32((UINTPTR)(pConfig->baseAddress + SOFTWARE_RESET_REG_OFFSET), SOFTWARE_RESET_BDRST);
}
u32 FSdCtrl_PrepareCmdRaw(FT_IN u32 cmdIndex, FT_IN u32 rspType)
{
u32 rawCmd = 0;
rawCmd |= CMD_SETTING_CMDI(cmdIndex);
switch (rspType)
{
case FTSDCTRL_CMD_RES_NONE:
rawCmd |= CMD_SETTING_RTS(0);
break;
case FTSDCTRL_CMD_RES_LONG:
rawCmd |= CMD_SETTING_RTS(1);
break;
case FTSDCTRL_CMD_RES_SHORT:
rawCmd |= CMD_SETTING_RTS(2);
break;
default:
rawCmd |= CMD_SETTING_RTS(0);
break;
}
return rawCmd;
}
void FSdCtrl_WriteData(FT_INOUT FtsdCtrl_t *pFtsdCtrl, FT_IN UINTPTR dataAddr,
FT_IN UINTPTR cardAddr, FT_IN u32 blkNum)
{
FSdCtrl_Config_t *pConfig;
Ft_assertVoid(FT_NULL != pFtsdCtrl);
pConfig = &pFtsdCtrl->config;
/* write 1 to clear data status register and command status register */
Ft_out32(pConfig->baseAddress + BD_ISR_REG, BD_ISR_REG_TRS);
Ft_out32(pConfig->baseAddress + NORMAL_INT_STATUS_REG, NORMAL_INT_STATUS_CC);
/* set DMA BD */
Ft_setBit32((UINTPTR)(pConfig->baseAddress + SOFTWARE_RESET_REG_OFFSET), SOFTWARE_RESET_BDRST);
Ft_clearBit32((UINTPTR)(pConfig->baseAddress + SOFTWARE_RESET_REG_OFFSET), SOFTWARE_RESET_BDRST);
/* set transfer lenth */
Ft_out32(pConfig->baseAddress + BLK_CNT_REG, blkNum);
/* set DMA discriptor data low address,data high address,card low address,card high address*/
Ft_out32(pConfig->baseAddress + DAT_IN_M_TX_BD, dataAddr);
Ft_out32(pConfig->baseAddress + DAT_IN_M_TX_BD, 0);
Ft_out32(pConfig->baseAddress + DAT_IN_M_TX_BD, cardAddr);
Ft_out32(pConfig->baseAddress + DAT_IN_M_TX_BD, 0);
}
void FSdCtrl_ReadData(FT_INOUT FtsdCtrl_t *pFtsdCtrl,
FT_IN UINTPTR dataAddr,
FT_IN UINTPTR cardAddr,
FT_IN u32 blkNum)
{
FSdCtrl_Config_t *pConfig;
Ft_assertVoid(FT_NULL != pFtsdCtrl);
pConfig = &pFtsdCtrl->config;
/* clear data status register and command status register */
Ft_out32(pConfig->baseAddress + BD_ISR_REG, BD_ISR_EN_ETRS);
Ft_out32(pConfig->baseAddress + NORMAL_INT_STATUS_REG, NORMAL_INT_EN_ECC);
/* set DMA BD */
Ft_setBit32((UINTPTR)(pConfig->baseAddress + SOFTWARE_RESET_REG_OFFSET), SOFTWARE_RESET_BDRST);
Ft_clearBit32((UINTPTR)(pConfig->baseAddress + SOFTWARE_RESET_REG_OFFSET), SOFTWARE_RESET_BDRST);
/* set transfer lenth */
Ft_out32(pConfig->baseAddress + BLK_CNT_REG, blkNum);
/* set DMA discriptor data low address,data high address,card low address,card high address*/
Ft_out32(pConfig->baseAddress + DAT_IN_M_RX_BD, dataAddr);
Ft_out32(pConfig->baseAddress + DAT_IN_M_RX_BD, 0);
Ft_out32(pConfig->baseAddress + DAT_IN_M_RX_BD, cardAddr);
Ft_out32(pConfig->baseAddress + DAT_IN_M_RX_BD, 0);
}
static ft_error_t FsdCtrl_privateSendCmd(FT_INOUT FtsdCtrl_t *pFtsdCtrl, FT_IN pFtsdCtrl_delayTimer_t pDelayTimer_fun, FT_IN u32 cmd, FT_IN u32 respType, FT_IN u32 arg)
{
u32 temp;
u32 sd_cmd;
u32 sd_arg;
FSdCtrl_Config_t *pConfig;
Ft_assertNonvoid(FT_NULL != pFtsdCtrl);
pConfig = &pFtsdCtrl->config;
/* enable cmd finished irq */
Ft_out32(pConfig->baseAddress + NORMAL_INT_STATUS_REG, NORMAL_INT_EN_ECC);
Ft_out32(pConfig->baseAddress + NORMAL_INT_STATUS_REG, 0);
Ft_out32(pConfig->baseAddress + ERROR_INT_STATUS_REG, BD_ISR_EN_ETRS);
Ft_out32(pConfig->baseAddress + ERROR_INT_STATUS_REG, 0);
/* prepare cmd msg, along with arg */
sd_cmd = FSdCtrl_PrepareCmdRaw(cmd, respType);
sd_arg = arg;
/* send cmd and arg */
Ft_out32(pConfig->baseAddress + CMD_SETTING_REG_OFFSET, sd_cmd);
Ft_out32(pConfig->baseAddress + ARGUMENT_REG_OFFSET, sd_arg);
if (pConfig->workMode & FTSDCTRL_CMD_IRQ_MASK)
{
if (pFtsdCtrl->cmdWaitCallback)
{
/* if irq is enabled and call back registered, enter call back procedure */
return pFtsdCtrl->cmdWaitCallback(pFtsdCtrl);
}
else
{
return FTSDC_INVALID_PARAM;
}
}
else
{
temp = Ft_in32(pConfig->baseAddress + NORMAL_INT_STATUS_REG);
/* polling wait for cmd-finished response */
while (NORMAL_INT_STATUS_CC != (temp & NORMAL_INT_STATUS_CC))
{
temp = Ft_in32(pConfig->baseAddress + NORMAL_INT_STATUS_REG);
pDelayTimer_fun(1);
}
}
return FTSDC_SUCCESS;
}
ft_error_t FSdCtrl_WaitWriteDataEnd(FT_INOUT FtsdCtrl_t *pFtsdCtrl,
FT_IN pFtsdCtrl_delayTimer_t pDelayTimer_fun,
FT_IN u32 blkNum)
{
u32 status;
u32 statusMask;
ft_error_t ret;
s32 timeout = 1000;
FSdCtrl_Config_t *pConfig;
Ft_assertNonvoid(FT_NULL != pFtsdCtrl);
pConfig = &pFtsdCtrl->config;
if (pConfig->workMode & FTSDCTRL_DATA_WRITE_IRQ_MASK)
{
/* enter irq mode */
if (NULL == pFtsdCtrl->writeWaitCallback)
{
return FTSDC_INVALID_PARAM;
}
ret = pFtsdCtrl->writeWaitCallback(pFtsdCtrl);
if (FTSDC_SUCCESS != ret)
{
return FTSDC_EILSEQ;
}
}
else
{
/* wait for DMA-error or DMA-finished status */
statusMask = BD_ISR_REG_DAIS | BD_ISR_REG_TRS;
do
{
status = (Ft_in32(pConfig->baseAddress + BD_ISR_REG) & statusMask);
pDelayTimer_fun(1);
timeout--;
} while ((!status) && timeout);
if (status & BD_ISR_REG_DAIS)
{
if (status & (BD_ISR_REG_TRE | BD_ISR_REG_NRCRC | BD_ISR_REG_CMDE))
{
return FTSDC_EILSEQ;
}
else if (!timeout)
{
return FTSDC_TIMEOUT;
}
}
}
/* multi block needs MMC_STOP_TRANSMISSION to stop process*/
if (blkNum > 1)
{
return FsdCtrl_privateSendCmd(pFtsdCtrl, pDelayTimer_fun, 12, CMD_SETTING_RTS(2), 0);
}
return FTSDC_SUCCESS;
}
ft_error_t FSdCtrl_WaitReadDataEnd(FT_INOUT FtsdCtrl_t *pFtsdCtrl,
FT_IN pFtsdCtrl_delayTimer_t pDelayTimer_fun,
FT_IN u32 blkNum)
{
u32 status;
u32 statusMask;
ft_error_t ret;
s32 timeout = 1000;
FSdCtrl_Config_t *pConfig;
Ft_assertNonvoid(FT_NULL != pFtsdCtrl);
pConfig = &pFtsdCtrl->config;
if (pConfig->workMode & FTSDCTRL_DATA_READ_IRQ_MASK)
{
if (pFtsdCtrl->readWaitCallback)
{
ret = pFtsdCtrl->readWaitCallback(pFtsdCtrl);
if (FTSDC_SUCCESS != ret)
{
return FTSDC_EILSEQ;
}
}
else
{
return FTSDC_INVALID_PARAM;
}
}
else
{
/* wait for DMA-error or Read-finish status */
statusMask = BD_ISR_REG_DAIS | BD_ISR_REG_RESPE;
do
{
status = (Ft_in32(pConfig->baseAddress + BD_ISR_REG) & statusMask);
pDelayTimer_fun(1);
timeout--;
} while ((!status) && timeout);
if (status & BD_ISR_REG_DAIS)
{
/* error handle */
if (status & (BD_ISR_REG_TRE | BD_ISR_REG_NRCRC | BD_ISR_REG_CMDE))
{
return FTSDC_EILSEQ;
}
else if (!timeout)
{
return FTSDC_TIMEOUT;
}
}
}
// /* multi block needs MMC_STOP_TRANSMISSION to stop process*/
if (blkNum > 1)
{
return FsdCtrl_privateSendCmd(pFtsdCtrl, pDelayTimer_fun, 12, CMD_SETTING_RTS(2), 0);
}
return FTSDC_SUCCESS;
}
ft_error_t FSdCtrl_WaitCmdEnd(FT_OUT FtsdCtrl_t *pFtsdCtrl,
FT_IN pFtsdCtrl_delayTimer_t pDelayTimer_fun,
FT_IN u32 rspType,
FT_OUT u32 *cmdRsp)
{
u32 status;
u32 statusMask;
s32 timeout = 1000;
const FSdCtrl_Config_t *pConfig;
ft_error_t result = FST_SUCCESS;
Ft_assertNonvoid(FT_NULL != pFtsdCtrl);
pConfig = &pFtsdCtrl->config;
if (pConfig->workMode & FTSDCTRL_CMD_IRQ_MASK)
{
if (pFtsdCtrl->cmdWaitCallback)
{
result = pFtsdCtrl->cmdWaitCallback(pFtsdCtrl);
}
else
{
return FTSDC_INVALID_PARAM;
}
status = Ft_in32(pConfig->baseAddress + NORMAL_INT_STATUS_REG);
}
else
{
/* wait for cmd-error or cmd-finish respones */
statusMask = NORMAL_INT_STATUS_EI | NORMAL_INT_STATUS_CC;
do
{
status = (Ft_in32(pConfig->baseAddress + NORMAL_INT_STATUS_REG) & statusMask);
pDelayTimer_fun(1);
timeout--;
} while ((!status) && timeout);
}
if (status & NORMAL_INT_STATUS_EI)
{
/* error handle */
status = Ft_in32(pConfig->baseAddress + ERROR_INT_STATUS_REG);
if (!timeout)
{
return FTSDC_TIMEOUT;
}
else if ((status & NORMAL_INT_EN_ECCRCE))
{
return FTSDC_EILSEQ;
}
}
if (rspType != FTSDCTRL_CMD_RES_NONE)
{
/* get cmd respones */
if (rspType == FTSDCTRL_CMD_RES_LONG)
{
cmdRsp[0] = Ft_in32(pConfig->baseAddress + CMD_RESP_1);
cmdRsp[1] = Ft_in32(pConfig->baseAddress + CMD_RESP_2);
cmdRsp[2] = Ft_in32(pConfig->baseAddress + CMD_RESP_3);
cmdRsp[3] = Ft_in32(pConfig->baseAddress + CMD_RESP_4);
}
else
{
cmdRsp[0] = Ft_in32(pConfig->baseAddress + CMD_RESP_1);
cmdRsp[1] = 0;
cmdRsp[2] = 0;
cmdRsp[3] = 0;
}
}
return result;
}
void FSdCtrl_DoCmd(FT_INOUT FtsdCtrl_t *pFtsdCtrl,
FT_IN u32 cmdIndex,
FT_IN u32 rspType,
u32 arg)
{
u32 cmd;
FSdCtrl_Config_t *pConfig;
Ft_assertVoid(FT_NULL != pFtsdCtrl);
pConfig = &pFtsdCtrl->config;
/* clear normal interrupt status */
Ft_out32(pConfig->baseAddress + NORMAL_INT_STATUS_REG, NORMAL_INT_STATUS_EI);
/* set command*/
cmd = FSdCtrl_PrepareCmdRaw(cmdIndex, rspType);
Ft_out32(pConfig->baseAddress + CMD_SETTING_REG_OFFSET, cmd);
if (cmdIndex == 41)
{
arg = 0x40ff8000;
}
Ft_out32(pConfig->baseAddress + ARGUMENT_REG_OFFSET, arg);
}
void FSdCtrl_DoACmd(FT_INOUT FtsdCtrl_t *pFtsdCtrl,
FT_IN u32 cmdIndex,
FT_IN u32 rspType,
u32 arg)
{
u32 cmd;
FSdCtrl_Config_t *pConfig;
Ft_assertVoid(FT_NULL != pFtsdCtrl);
pConfig = &pFtsdCtrl->config;
/* clear normal interrupt status */
Ft_out32(pConfig->baseAddress + NORMAL_INT_STATUS_REG, NORMAL_INT_EN_ECC);
/* set command*/
cmd = FSdCtrl_PrepareCmdRaw(cmdIndex, rspType);
cmd |= CMD_SETTING_TRTY(2);
Ft_out32(pConfig->baseAddress + CMD_SETTING_REG_OFFSET, cmd);
}
void FSdCtrl_WriteWaitRegister(FT_INOUT FtsdCtrl_t *pFtsdCtrl, FT_IN pFtsdCtrl_irqWaitCallback_t callBack)
{
Ft_assertVoid(FT_NULL != pFtsdCtrl);
pFtsdCtrl->writeWaitCallback = callBack;
}
void FSdCtrl_ReadWaitRegister(FT_INOUT FtsdCtrl_t *pFtsdCtrl, FT_IN pFtsdCtrl_irqWaitCallback_t callBack)
{
Ft_assertVoid(FT_NULL != pFtsdCtrl);
pFtsdCtrl->readWaitCallback = callBack;
}
void FSdCtrl_CmdWaitRegister(FT_INOUT FtsdCtrl_t *pFtsdCtrl, FT_IN pFtsdCtrl_irqWaitCallback_t callBack)
{
Ft_assertVoid(FT_NULL != pFtsdCtrl);
pFtsdCtrl->cmdWaitCallback = callBack;
}
u32 FSdCtrl_GetNormalIrqStatus(FT_INOUT FtsdCtrl_t *pFtsdCtrl)
{
Ft_assertNonvoid(FT_NULL != pFtsdCtrl);
FSdCtrl_Config_t *pConfig;
pConfig = &pFtsdCtrl->config;
return Ft_in32(pConfig->baseAddress + NORMAL_INT_STATUS_REG);
}
u32 FSdCtrl_GetDataIrqStatus(FT_INOUT FtsdCtrl_t *pFtsdCtrl)
{
Ft_assertNonvoid(FT_NULL != pFtsdCtrl);
FSdCtrl_Config_t *pConfig;
pConfig = &pFtsdCtrl->config;
return Ft_in32(pConfig->baseAddress + BD_ISR_REG);
}
u32 FSdCtrl_GetErrorIrqStatus(FT_INOUT FtsdCtrl_t *pFtsdCtrl)
{
Ft_assertNonvoid(FT_NULL != pFtsdCtrl);
FSdCtrl_Config_t *pConfig;
pConfig = &pFtsdCtrl->config;
return Ft_in32(pConfig->baseAddress + ERROR_INT_STATUS_REG);
}

View File

@ -0,0 +1,235 @@
/*
 * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
 *
 * SPDX-License-Identifier: Apache-2.0.
 *
* @Date: 2021-03-31 14:59:20
* @LastEditTime: 2021-04-19 17:04:44
* @Description:  This files is for implementation of sd ctrl
*
* @Modify History: * * Ver   Who        Date         Changes
* ----- ------     --------    --------------------------------------
*/
#ifndef FTSDCTRL_H
#define FTSDCTRL_H
#include "ft_types.h"
#include "ft_error_code.h"
/* sd ctrl module debug tag */
#define FT_SD_CTRL_DEBUG_TAG "FT_SD_CTRL"
/* definition of errcode for sd module */
#define FTSDC_SUCCESS FST_SUCCESS /* 成功 */
#define FTSDC_FAILURE FT_MAKE_ERRCODE(errModeSdCtrl, errBspGeneral, FST_FAILURE) /* Normal */
#define FTSDC_TIMEOUT FT_MAKE_ERRCODE(errModeSdCtrl, errBspGeneral, FST_TIMEOUT) /* Timeout */
#define FTSDC_EILSEQ FT_MAKE_ERRCODE(errModeSdCtrl, errBspGeneral, FST_EILSEQ) /* Illegal byte sequence. */
#define FTSDC_INVALID_PARAM FT_MAKE_ERRCODE(errModeSdCtrl, errBspGeneral, FST_INVALID_PARAM) /* Illegal byte sequence. */
/* type of response to sd cmds */
#define FTSDCTRL_CMD_RES_NONE 0 /* No response */
#define FTSDCTRL_CMD_RES_LONG 1 /* The response length is long, code length is 128 */
#define FTSDCTRL_CMD_RES_SHORT 2 /* The response length is short, code length is 32 */
/* irq enable bits */
#define FTSDCTRL_DATA_WRITE_IRQ_MASK 0x1
#define FTSDCTRL_DATA_READ_IRQ_MASK 0x2
#define FTSDCTRL_CMD_IRQ_MASK 0x4
/* type of irq callback */
typedef enum
{
FTSDCTRL_DMADATAIRQID = 0x1U, /* Select dma interrupt */
FTSDCTRL_CMDIRQID = 0x2U, /* Select cmd interrupt */
FTSDCTRL_ERRORIRQID = 0x3U, /* Select error interrupt */
} FSdCtrl_IrqCallbackSelect_t;
/* normal irq enable bits for NORMAL_INT_EN_REG_OFFSET */
typedef enum
{
NORMAL_IRQ_CC = 1, /* Command completion interrupt */
NORMAL_IRQ_CR = 2, /* Card removal interrupt */
NORMAL_IRQ_EI = 4 /* Command error interrupt */
} FSdCtrl_NormalIrqSelect_t;
/* error irq enable bits for ERROR_INT_EN_REG_OFFSET */
typedef enum
{
ERROR_IRQ_CTE = 1, /* Command timeout error interrupted */
ERROR_IRQ_CCRCE = 2, /* Command CRC error interrupt */
ERROR_IRQ_CIR = 4, /* Command index error interrupt */
ERROR_IRQ_CNR = 8 /* Command response error interrupted */
} FSdCtrl_ErrorIrqSelect_t;
/* data trans irq bits for BD_ISR_EN_REG_OFFSET */
typedef enum
{
BD_IRQ_TRS = 1, /* DMA transmission has been interrupted */
BD_IRQ_DTE = 2, /* Timeout interrupt */
BD_IRQ_CMDE = 4, /* Command response error interrupted */
BD_IRQ_TRE = 8, /* Command response error interrupt CRC response error interrupt */
BD_IRQ_NRCRC = 0x10, /* No CRC response interruption */
BD_IRQ_DATFRAX = 0x20, /* AXI bus forces to release interrupts */
BD_IRQ_RESPE = 0x40, /* Read SD card operation, AXI BR channel complete interrupt */
BD_IRQ_DAIS = 0x80, /* DMA error interrupt */
} FSdCtrl_BdIrqSelect;
/* types of irq */
typedef enum
{
FTSDC_NORMAL_ISR = 0U,
FTSDC_BD_ISR,
FTSDC_ERROR_ISR
} FSdCtrl_IsrCallbackSelect_t;
/* voltage supply range type of SD Card follow POWER_CONTROLL_REG
*/
typedef enum
{
FSDC_HIGH_V = 0, /* SD card operate within the voltage range of 2.7-3.6 V */
FSDC_DUAL_V, /* SD card operate within the Low Voltage Range (T.B.D) and 2.7-3.6 V */
MAX_FSDC_VOLTAGE_TYPE
} FSdCtrl_VRangeType_t;
/* read-write property of SD Card */
typedef enum
{
FSDC_RW_CARD = 0,
FSDC_RO_CARD,
MAX_FSDC_WR_CARD_TYPE
} FSdCtrl_WRType_t;
/* capacity type of SD Card */
typedef enum
{
FSDC_SD_CARD = 0,
FSDC_SDHC_CARD,
FSDC_SDXC_CARD,
MAX_FSDC_CARD_CAPACITY_TYPE
} FSdCtrl_CapacityType_t;
/* speed class of SD Card */
typedef enum
{
FSDC_CLASS0 = 0,
FSDC_CLASS2,
FSDC_CLASS4,
FSDC_CLASS6,
MAX_FSDC_CLASS_TYPE
} FSdCtrl_ClassType_t;
/**
* This typedef contains configuration information for the sd device.
*/
typedef struct
{
u32 instanceId; /* Unique ID of device */
u32 baseAddress; /* Base address of the device */
u32 inputClockHz; /* Input clock frequency */
u32 cardDetect; /* Card Detect */
u32 writeProtect; /* Write Protect */
u32 busWidth; /* Bus Width */
u32 dmaIrqNum; /* dma irq number */
u32 normalIrqNum; /* normal irq number */
u32 errIrqNum; /* error irq number */
u8 workMode; /* Work mode for data transfers ,
If the mask bit is 0, polling is used ,
follow irq enable bits*/
} FSdCtrl_Config_t;
typedef void (*FtsdCtrl_irqCallback_t)(void *args);
/* irq callback and iput args */
typedef struct
{
FtsdCtrl_irqCallback_t pDmaDataCallback; /* DMA data interrupt function pointer */
void *pDmaDataArgs;
FtsdCtrl_irqCallback_t pCmdCallback; /* Commond interrupt function pointer */
void *pCmdArgs;
FtsdCtrl_irqCallback_t pErrorCallback; /* Error interrupt function pointer */
void *pErrorArgs;
} FSdCtrl_IrqConfig_t;
typedef struct FtsdCtrl FtsdCtrl_t;
typedef void (*pFtsdCtrl_delayTimer_t)(ft_base_t delayUs);
typedef ft_error_t (*pFtsdCtrl_irqWaitCallback_t)(FtsdCtrl_t *FtsdCtrl);
/* ctrl instance of sd */
struct FtsdCtrl
{
FSdCtrl_Config_t config;
u32 isReady; /* Device is initialized and ready */
/*************reserved**************/
FSdCtrl_VRangeType_t voltageType;
FSdCtrl_WRType_t writeReadType;
FSdCtrl_CapacityType_t capacityType;
FSdCtrl_ClassType_t speedClassType;
/*************reserved**************/
FSdCtrl_IrqConfig_t irqConfig;
pFtsdCtrl_irqWaitCallback_t writeWaitCallback; /* function pointer .Used to determine whether the data transmission is complete*/
pFtsdCtrl_irqWaitCallback_t readWaitCallback; /* function pointer .Used to determine whether the data received is complete*/
pFtsdCtrl_irqWaitCallback_t cmdWaitCallback; /* function pointer . Used to determine whether the command is complete */
};
u32 FSdCtrl_PrepareCmdRaw(FT_IN u32 cmdIndex, FT_IN u32 rspType);
void FSdCtrl_WriteData(FT_INOUT FtsdCtrl_t *pFtsdCtrl, FT_IN UINTPTR dataAddr, FT_IN UINTPTR cmdArg, FT_IN u32 blkNum);
void FSdCtrl_ReadData(FT_INOUT FtsdCtrl_t *pFtsdCtrl,
FT_IN UINTPTR dataAddr,
FT_IN UINTPTR cardAddr,
FT_IN u32 blkNum);
ft_error_t FSdCtrl_WaitCmdEnd(FT_OUT FtsdCtrl_t *pFtsdCtrl,
FT_IN pFtsdCtrl_delayTimer_t pDelayTimer_fun,
FT_IN u32 rspType,
FT_OUT u32 *cmdRsp);
ft_error_t FSdCtrl_WaitReadDataEnd(FT_INOUT FtsdCtrl_t *pFtsdCtrl,
FT_IN pFtsdCtrl_delayTimer_t pDelayTimer_fun,
FT_IN u32 blkNum);
ft_error_t FSdCtrl_WaitWriteDataEnd(FT_INOUT FtsdCtrl_t *pFtsdCtrl,
FT_IN pFtsdCtrl_delayTimer_t pDelayTimer_fun,
FT_IN u32 blkNum);
void FSdCtrl_DoCmd(FT_INOUT FtsdCtrl_t *pFtsdCtrl, FT_IN u32 cmdIndex, FT_IN u32 rspType, u32 arg);
void FSdCtrl_DoACmd(FT_INOUT FtsdCtrl_t *pFtsdCtrl,
FT_IN u32 cmdIndex,
FT_IN u32 rspType,
u32 arg);
void FSdCtrl_NormalIrq(FT_INOUT FtsdCtrl_t *pFtsdCtrl);
void FSdCtrl_DmaIrq(FT_INOUT FtsdCtrl_t *pFtsdCtrl);
void FSdCtrl_ErrIrq(FT_INOUT FtsdCtrl_t *pFtsdCtrl);
bool_t FSdCtrl_CardDetect(FT_INOUT FtsdCtrl_t *pFtsdCtrl);
FSdCtrl_Config_t *FSdCtrl_LookupConfig(u32 instanceId);
/* This routine performs per device specific initialization of Phytium SDHC.*/
ft_error_t FsdCtrl_Init(FT_INOUT FtsdCtrl_t *pFtsdCtrl);
void FSdCtrl_ClkFreqSetup(FT_INOUT FtsdCtrl_t *pFtsdCtrl, FT_IN u32 sdClk);
void FSdCtrl_ResetDma(FT_INOUT FtsdCtrl_t *pFtsdCtrl);
/* reset sd ctrl during init */
void FSdCtrl_Reset(FT_INOUT FtsdCtrl_t *pFtsdCtrl, pFtsdCtrl_delayTimer_t fDelayTimer);
/* set irq call backs */
ft_error_t FSdCtrl_SetHandler(FT_INOUT FtsdCtrl_t *pFtsdCtrl, FT_IN FSdCtrl_IrqCallbackSelect_t selectIndex,
void *FuncPtr,
void *Args);
/* register call-backs to determinate wheather write、read and cmd is complete */
void FSdCtrl_WriteWaitRegister(FT_INOUT FtsdCtrl_t *pFtsdCtrl, FT_IN pFtsdCtrl_irqWaitCallback_t callBack);
void FSdCtrl_ReadWaitRegister(FT_INOUT FtsdCtrl_t *pFtsdCtrl, FT_IN pFtsdCtrl_irqWaitCallback_t callBack);
void FSdCtrl_CmdWaitRegister(FT_INOUT FtsdCtrl_t *pFtsdCtrl, FT_IN pFtsdCtrl_irqWaitCallback_t callBack);
void FSdCtrl_ErrWaitRegister(FT_INOUT FtsdCtrl_t *pFtsdCtrl, FT_IN pFtsdCtrl_irqWaitCallback_t callBack);
/* get irq status */
u32 FSdCtrl_GetNormalIrqStatus(FT_INOUT FtsdCtrl_t *pFtsdCtrl);
u32 FSdCtrl_GetDataIrqStatus(FT_INOUT FtsdCtrl_t *pFtsdCtrl);
u32 FSdCtrl_GetErrorIrqStatus(FT_INOUT FtsdCtrl_t *pFtsdCtrl);
/* enable selected normal irq */
void FSdCtrl_NormalIrqSet(FtsdCtrl_t *pFtsdCtrl, FT_IN FSdCtrl_NormalIrqSelect_t flgs);
void FSdCtrl_BdIrqSet(FtsdCtrl_t *pFtsdCtrl, FT_IN FSdCtrl_BdIrqSelect flgs);
#endif //

View File

@ -0,0 +1,31 @@
/*
 * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
 *
 * SPDX-License-Identifier: Apache-2.0.
 *
* @Date: 2021-03-31 14:59:20
* @LastEditTime: 2021-05-24 14:34:13
* @Description:  This files is for sd ctrl config definition
*
* @Modify History: * * Ver   Who        Date         Changes
* ----- ------     --------    --------------------------------------
*/
#include "ft_sdctrl.h"
#include "ft_parameters.h"
/* configs of sd ctrl */
FSdCtrl_Config_t FSdCtrl_Config[FT_SDC_NUM] =
{
{
.instanceId = FT_SDC_INSTANCE,
.baseAddress = FT_SDC_BASEADDR,
.inputClockHz = FT_SDC_FREQ,
.cardDetect = 1,
.writeProtect = 0,
.busWidth = 1,
.dmaIrqNum = 52,
.normalIrqNum = 53,
.errIrqNum = 54,
.workMode = 0 /*FTSDCTRL_CMD_IRQ_MASK | FTSDCTRL_DATA_WRITE_IRQ_MASK | FTSDCTRL_DATA_READ_IRQ_MASK*/
}};

View File

@ -0,0 +1,41 @@
/*
 * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
 *
 * SPDX-License-Identifier: Apache-2.0.
 *
* @Date: 2021-03-31 14:59:20
* @LastEditTime: 2021-05-25 16:46:46
* @Description:  This files is for sd ctrl register-related implementations
*
* @Modify History: * * Ver   Who        Date         Changes
* ----- ------     --------    --------------------------------------
*/
#include "ft_sdctrl_hw.h"
#include "ft_sdctrl.h"
#include "ft_io.h"
#include "ft_types.h"
#include "ft_assert.h"
#include "ft_generic_timer.h"
void FSdCtrl_Reset(FT_INOUT FtsdCtrl_t *pFtsdCtrl, pFtsdCtrl_delayTimer_t fDelayTimer)
{
FSdCtrl_Config_t *pConfig;
Ft_assertVoid(FT_NULL != pFtsdCtrl);
pConfig = &pFtsdCtrl->config;
/* trigger software reset for 1us */
Ft_setBit32(pConfig->baseAddress + SOFTWARE_RESET_REG_OFFSET, SOFTWARE_RESET_SRST);
/* Wait for reset is ok */
Ft_GenericTimer_UsDelay(1);
Ft_clearBit32(pConfig->baseAddress + SOFTWARE_RESET_REG_OFFSET, SOFTWARE_RESET_SRST);
/* wait dat[0] to be high-lev */
while ((!(Ft_in32(pConfig->baseAddress + STATUS_REG) & STATUS_REG_DLSL(1))))
{
fDelayTimer(1);
}
return;
}

View File

@ -0,0 +1,210 @@
/*
 * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
 *
 * SPDX-License-Identifier: Apache-2.0.
 *
* @Date: 2021-03-31 14:59:20
* @LastEditTime: 2021-04-19 16:17:39
* @Description:  This files is for sd ctrl register
*
* @Modify History: * * Ver   Who        Date         Changes
* ----- ------     --------    --------------------------------------
*/
#ifndef _SDCTRL_HW_H
#define _SDCTRL_HW_H
#include "ft_sdctrl.h"
/* Register Offset */
#define CONTROLL_SETTING_REG_OFFSET 0x00 /* Controller configuration register */
#define ARGUMENT_REG_OFFSET 0x04 /* Parameter register */
#define CMD_SETTING_REG_OFFSET 0x08 /* Command register */
#define CLOCK_DIV_REG_OFFSET 0x0C /* Clock division register */
#define SOFTWARE_RESET_REG_OFFSET 0x10 /* Reset control register */
#define POWER_CONTROLL_REG_OFFSET 0x14 /* Power control register */
#define TIMEOUT_CMD_REG_OFFSET 0x18 /* cmd Timeout setting register */
#define TIMEOUT_DATA_REG_OFFSET 0x1C /* Data timeout setting register */
#define NORMAL_INT_EN_REG_OFFSET 0x20 /* Interrupt Enable Register */
#define ERROR_INT_EN_REG_OFFSET 0x24 /* error Interrupt Enable Register */
#define BD_ISR_EN_REG_OFFSET 0x28 /* Data Transfer Interrupt Enable Register */
#define CAPABILIES_REG_OFFSET 0x2c /* capabilies register */
#define SD_DRV_REG_OFFSET 0x30 /* SD card driver phase register */
#define SD_SAMP_REG_OFFSET 0x34 /* SD card sampling phase register */
#define SD_SEN_REG_OFFSET 0x38 /* Card detection controller */
#define HDS_AXI_REG_CONF1_OFFSET 0x3c /* AXI boundary configuration register 1 */
#define DAT_IN_M_RX_BD 0x40 /* SD BD RX address register */
#define DAT_IN_M_TX_BD 0x60 /* SD BD TX address register */
#define BLK_CNT_REG 0x80 /* Block reads and writes configuration registers */
#define HDS_AXI_REG_CONF2 0xa8 /* AXI boundary configuration register 2 */
#define NORMAL_INT_STATUS_REG 0xc0 /* Interrupt status register */
#define ERROR_INT_STATUS_REG 0xc4 /* ERROR interrupt register */
#define BD_ISR_REG 0xc8 /* Data Transfer Interrupt Status Register */
#define BD_STATUS 0xcc /* BD descriptor register */
#define STATUS_REG 0xd0 /* state register */
#define BLOCK 0xd4 /* Block length register */
#define CMD_RESP_1 0xe0 /* Command response register 1 */
#define CMD_RESP_2 0xe4 /* Command response register 2 */
#define CMD_RESP_3 0xe8 /* Command response register 3 */
#define CMD_RESP_4 0xec /* Command response register 4 */
/* Controller configuration register */
#define CONTROLL_SETTING_PERMDR(x) ((x & 3) << 8) /* Read operation corresponding to the size of the end selection: 00: small end alignment,01: large end alignment,10: SD protocol mode */
#define CONTROLL_SETTING_PERMDW(x) ((x & 3) << 10) /* Write operation corresponding to the size of the endian selection: 00: small endian alignment 01: large endian alignment 10: SD protocol mode*/
/* Parameter register */
#define ARGUMENT_REG(x) (x & 0xffffffff)
/* Command register */
#define CMD_SETTING_RTS(x) ((x & 3) << 0) /* 0: No response 01: Response byte length 136 10: Response byte length 48 11: Response byte length 48 */
#define CMD_SETTING_CRCE (1U << 3) /* 0: CRC check is not performed on CMD response 1: CRC check is performed on CMD response */
#define CMD_SETTING_CICE (1U << 4) /* 0CMD 响应时,不执行索引检查 1CMD 响应时,执行索引检查 */
#define CMD_SETTING_CMDW(x) ((x & 3) << 6)
#define CMD_SETTING_CMDI(x) ((x & 0x3f) << 8) /* 命令索引 */
#define CMD_SETTING_TRTY(x) ((x & 3) << 14) /* 10 adtc 指令 ,其它: 读写操作 */
/* 时钟分频寄存器 */
#define CLOCK_DIV_RE(x) (x & 0xffffffff) /* CLKD-时钟分频系数 SD_frequency= 600M/ (2*(clock_d+1)) */
/* 复位控制寄存器 */
#define SOFTWARE_RESET_SRST (1U) /* 控制器软复位 */
#define SOFTWARE_RESET_BDRST (4U) /* DMA BD 清 0 */
#define SOFTWARE_RESET_CFCLF (8U) /* 卡插入拔出状态触发标志清 0 */
/* cmd 超时设置寄存器 */
#define TIMEOUT_CMD_REG(x) (x & 0xffffffff) /* command 超时参数 */
/* 数据超时设置寄存器 */
#define TIMEOUT_DATA_REG(x) (x & 0xffffffff) /* data 超时参数 */
/* 中断使能寄存器 */
#define NORMAL_INT_EN_ECC 1U /* 命令完成中断使能 */
#define NORMAL_INT_EN_ECCRCE 2U /* 卡拔出中断使能 */
#define NORMAL_INT_EN_ECIE (1U << 15) /* 错误中断使能 */
/* error 中断使能寄存器 */
#define ERROR_INT_EN_CNR (1U << 4) /* Command response error interrupted */
#define ERROR_INT_EN_CIR (1U << 3) /* 命令索引错误中断使能 */
#define ERROR_INT_EN_CCRCE (1U << 1) /* 命令 CRC 错误中断使能 */
#define ERROR_INT_EN_CTE (1U << 0) /* 命令超时中断使能 */
/* 数据传输中断使能寄存器 */
#define BD_ISR_EN_ETRS (1U << 0) /* DMA 传输完成中断使能 */
#define BD_ISR_EN_EDTE (1U << 3) /* 数据超时中断使能 */
#define BD_ISR_EN_ECMDE (1U << 4) /* 命令响应错误中断使能 */
#define BD_ISR_EN_ETRE (1U << 5) /* 传输错误中断使能 */
#define BD_ISR_EN_ENRCRCE (1U << 6) /* CRC 校验错误中断使能 */
#define BD_ISR_EN_EDATFRAXE (1U << 7) /* AXI 总线错误中断使能 */
#define BD_ISR_EN_RESPE (1U << 8) /* 读 SD 卡操作AXI BR 通道完成中断 */
#define BD_ISR_EN_EDAISE (1U << 15) /* DMA 错误中断使能 */
#define BD_ISR_ALL_MASK (BD_ISR_EN_ETRS | BD_ISR_EN_EDTE | \
BD_ISR_EN_ECMDE | BD_ISR_EN_ETRE | \
BD_ISR_EN_ENRCRCE | BD_ISR_EN_EDATFRAXE | \
BD_ISR_EN_RESPE | BD_ISR_EN_EDAISE)
/* 状态寄存器 */
#define CAPABILIES_REG(x) (x & 0xffffffff)
/* SD 卡驱动相位寄存器 */
#define SD_DRV_REG(x) (x & 0xffffffff) /* 卡驱动相位配置参数 */
/* SD 卡采样相位寄存器 */
#define SD_SAMP_REG(x) (x & 0xffffffff) /* 卡采样相位配置参数 */
#define SD_SAMP_DEFAULT 11 /* when SD card work in high-speed mode, \
the best sampling pharse is needed to \
get the correct data */
#define SD_FRRQ_DIV_DEFAULT 5 /* default freq div */
#define SD_CLK_FREQ_400KHZ 400000
#define SD_CLK_FREQ_25MHZ 25000000
/* 卡检测控制器 */
#define SD_SEN_REG_CREFR (1U << 1) /* 卡拔出时自动释放 AXI 总线选择 */
#define SD_SEN_REG_CRES (1U << 2) /* CARD 在位状态标志选择 0 卡在位-0不在位-1 1: 卡在位-1不在位-0 */
#define SD_SEN_REG_DEBNCE(x) ((x & 0xffffff) << 8) /* 去抖时钟分频参数 */
/* AXI 边界配置寄存器 1 */
#define HDS_AXI_REG_CONF1_AWDOMAIN_HDS_M(x) ((x & 0x3) << 0)
#define HDS_AXI_REG_CONF1_AWBAR_HDS_M(x) ((x & 0x3) << 2)
#define HDS_AXI_REG_CONF1_ARSNOOP_HDS_M(x) ((x & 0xf) << 4)
#define HDS_AXI_REG_CONF1_ARREGION_HDS_M(x) ((x & 0xf) << 8)
#define HDS_AXI_REG_CONF1_ARDOMAIN_HDS_M(x) ((x & 0x3) << 12)
#define HDS_AXI_REG_CONF1_ARBAR_HDS_M(x) ((x & 0x3) << 14)
#define HDS_AXI_REG_CONF1_AWSNOOP_HDS_M(x) ((x & 0x7) << 16)
#define HDS_AXI_REG_CONF1_AWREGION_HDS_M(x) ((x & 0xF) << 19)
/* SD BD RX 地址寄存器 */
#define DAT_IN_M_RX_BD_MASK(x) (x & 0xffffffff) /* dma 读卡地址配置4 个 cycle ,系统低 4B-系统高 4B-SD 低 4B- SD 高 4B */
/* SD BD TX 地址寄存器 */
#define DAT_IN_M_TX_BD_MASK(x) (x & 0xffffffff) /* dma 写卡地址配置4 个 cycle ,系统低 4B-系统高 4B-SD 低 4B- SD 高 4B */
/* 块读写配置寄存器 */
#define BLK_CNT(x) (x & 0xffffffff) /* dma block num setting */
/* AXI 边界配置寄存器 2 */
#define HDS_AXI_REG_CONF2_D_ARPROT(x) ((x & 0x7) << 27)
#define HDS_AXI_REG_CONF2_SD_AWPROT(x) ((x & 0x7) << 24)
#define HDS_AXI_REG_CONF2_SD_ARCACHE_M(x) ((x & 0xf) << 20)
#define HDS_AXI_REG_CONF2_SD_AWCACHE_M(x) ((x & 0xf) << 16)
#define HDS_AXI_REG_CONF2_RESERVED(x) ((x & 0x3) << 14)
#define HDS_AXI_REG_CONF2_HDA_ARPRO(x) ((x & 0x7) << 11)
#define HDS_AXI_REG_CONF2_HDA_AWPROT(x) ((x & 0x7) << 8)
#define HDS_AXI_REG_CONF2_HDA_ARCACHE_M(x) ((x & 0xf) << 4)
#define HDS_AXI_REG_CONF2_HDA_AWCACHE_M(x) ((x & 0xf) << 0)
/* 中断状态寄存器 */
#define NORMAL_INT_STATUS_EI (1U << 15) /* 命令错误中断 */
#define NORMAL_INT_STATUS_CR (1U << 1) /* 卡移除中断 */
#define NORMAL_INT_STATUS_CC 1U /* 命令完成中断 */
#define NORMAL_INT_STATUS_ALL_MASK (NORMAL_INT_STATUS_EI | NORMAL_INT_STATUS_CR | NORMAL_INT_STATUS_CC)
/* error 中断寄存器 */
#define ERROR_INT_STATUS_CNR (1U << 4) /* 命令响应错误中断 */
#define ERROR_INT_STATUS_CIR (1U << 3) /* 命令索引错误中断 */
#define ERROR_INT_STATUS_CCRCE (1U << 1) /* 命令 CRC 错误中断 */
#define ERROR_INT_STATUS_CTE 1U /* 命令超时错误中断 */
#define ERROR_INT_STATUS_ALL_MASK (ERROR_INT_STATUS_CNR | ERROR_INT_STATUS_CIR | ERROR_INT_STATUS_CCRCE | ERROR_INT_STATUS_CTE)
/* 数据传输中断状态寄存器 */
#define BD_ISR_REG_DAIS (1U << 15) /* DMA 错误中断*/
#define BD_ISR_REG_RESPE (1U << 8) /* 读 SD 卡操作AXI BR 通道完成中断*/
#define BD_ISR_REG_DATFRAX (1U << 7) /* axi 总线强制释放中断*/
#define BD_ISR_REG_NRCRC (1U << 6) /* 无 CRC 响应中断*/
#define BD_ISR_REG_TRE (1U << 5) /* CRC 响应错误中断*/
#define BD_ISR_REG_CMDE (1U << 4) /* 命令响应错误中断*/
#define BD_ISR_REG_DTE (1U << 3) /* 超时中断*/
#define BD_ISR_REG_TRS (1U << 0) /* DMA 传输完成中断*/
/* bd 描述符寄存器 */
#define BD_STATUS_REG(x) (x & 0xffffffff) /* bd 描述符寄存器 */
/* 状态寄存器 */
#define STATUS_REG_DATMAST(x) ((x & 0xf) << 27) /* data_master 状态机 */
#define STATUS_REG_CDIF (1U << 26) /* 卡在位标志 */
#define STATUS_REG_CDRF (1U << 25) /* 卡不在位标志 */
#define STATUS_REG_CLSL (1U << 24) /* 命令闲信号 */
#define STATUS_REG_DLSL(x) ((x & 0xf) << 20) /* 线信号 */
#define STATUS_REG_CDSL (1U << 19) /* 卡检测管脚信号 */
#define STATUS_REG_CST(x) ((x & 0xf) << 12) /* cmd_host state 状态机 */
#define STATUS_REG_CSM(x) ((x & 0X1F) << 7)
#define STATUS_REG_DAT_AVA (1 << 6) /* DAT_AVA 当前命令状态流程运转完 */
#define STATUS_REG_CRC_VALID (1 << 5)
#define STATUS_REG_CICMD 1U /* RO 0x0 CMD 总线状态 */
/* 块长度寄存器 */
#define BLOCK_RGE(x) (x & 0xffffffff) /* 块长度寄存器 */
/* 命令响应寄存器 1 */
#define CMD_RESP_1_REG(x) (x & 0xffffffff)
/* 命令响应寄存器 2 */
#define CMD_RESP_2_REG(x) (x & 0xffffffff)
/* 命令响应寄存器 3 */
#define CMD_RESP_3_REG(x) (x & 0xffffffff)
/* 命令响应寄存器 4 */
#define CMD_RESP_4_REG(x) (x & 0xffffffff)
#endif // !

View File

@ -0,0 +1,110 @@
/*
 * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
 *
 * SPDX-License-Identifier: Apache-2.0.
 *
* @Date: 2021-03-31 14:59:20
* @LastEditTime: 2021-05-25 16:46:54
* @Description:  This files is for sd ctrl irq handling
*
* @Modify History: * * Ver   Who        Date         Changes
* ----- ------     --------    --------------------------------------
*/
#include "ft_sdctrl.h"
#include "ft_sdctrl_hw.h"
#include "ft_assert.h"
#include "ft_types.h"
#include "ft_io.h"
#include "ft_printf.h"
#include "ft_debug.h"
#ifndef LOG_LOCAL_LEVEL
#define LOG_LOCAL_LEVEL FT_LOG_NONE
#endif
#define FT_SD_CTRL_DEBUG_I(format, ...) FT_DEBUG_PRINT_I(FT_SD_CTRL_DEBUG_TAG, format, ##__VA_ARGS__)
#define FT_SD_CTRL_DEBUG_E(format, ...) FT_DEBUG_PRINT_E(FT_SD_CTRL_DEBUG_TAG, format, ##__VA_ARGS__)
#define FT_SD_CTRL_DEBUG_W(format, ...) FT_DEBUG_PRINT_W(FT_SD_CTRL_DEBUG_TAG, format, ##__VA_ARGS__)
void FSdCtrl_NormalIrq(FT_INOUT FtsdCtrl_t *pFtsdCtrl)
{
FSdCtrl_Config_t *pConfig;
FSdCtrl_IrqConfig_t *irqConfig;
Ft_assertVoid(FT_NULL != pFtsdCtrl);
pConfig = &pFtsdCtrl->config;
irqConfig = &pFtsdCtrl->irqConfig;
//FT_SD_CTRL_DEBUG_I("enter cmd irq procedure\r\n");
if (irqConfig->pCmdCallback)
{
irqConfig->pCmdCallback(irqConfig->pCmdArgs);
}
/* clear interrupts */
Ft_out32(pConfig->baseAddress + NORMAL_INT_STATUS_REG, NORMAL_INT_STATUS_ALL_MASK);
Ft_out32(pConfig->baseAddress + NORMAL_INT_STATUS_REG, 0);
}
void FSdCtrl_DmaIrq(FT_INOUT FtsdCtrl_t *pFtsdCtrl)
{
FSdCtrl_Config_t *pConfig;
FSdCtrl_IrqConfig_t *irqConfig;
Ft_assertVoid(FT_NULL != pFtsdCtrl);
pConfig = &pFtsdCtrl->config;
irqConfig = &pFtsdCtrl->irqConfig;
if (irqConfig->pDmaDataCallback)
{
irqConfig->pDmaDataCallback(irqConfig->pDmaDataArgs);
}
/* clear interrupts */
Ft_out32(pConfig->baseAddress + BD_ISR_REG, BD_ISR_ALL_MASK);
Ft_out32(pConfig->baseAddress + BD_ISR_REG, 0);
}
void FSdCtrl_ErrIrq(FT_INOUT FtsdCtrl_t *pFtsdCtrl)
{
FSdCtrl_Config_t *pConfig;
FSdCtrl_IrqConfig_t *irqConfig;
Ft_assertVoid(FT_NULL != pFtsdCtrl);
pConfig = &pFtsdCtrl->config;
irqConfig = &pFtsdCtrl->irqConfig;
if (irqConfig->pErrorCallback)
{
irqConfig->pErrorCallback(irqConfig->pErrorArgs);
}
/* clear interrupts */
Ft_out32(pConfig->baseAddress + ERROR_INT_STATUS_REG, ERROR_INT_STATUS_ALL_MASK);
Ft_out32(pConfig->baseAddress + ERROR_INT_STATUS_REG, 0);
}
ft_error_t FSdCtrl_SetHandler(FT_INOUT FtsdCtrl_t *pFtsdCtrl, FT_IN FSdCtrl_IrqCallbackSelect_t selectIndex,
void *FuncPtr, void *Args)
{
Ft_assertNonvoid(pFtsdCtrl != NULL);
Ft_assertNonvoid(FuncPtr != NULL);
Ft_assertNonvoid(pFtsdCtrl->isReady == FT_COMPONENT_IS_READLY);
switch (selectIndex)
{
case FTSDCTRL_DMADATAIRQID:
pFtsdCtrl->irqConfig.pDmaDataCallback = FuncPtr;
pFtsdCtrl->irqConfig.pDmaDataArgs = Args;
break;
case FTSDCTRL_CMDIRQID:
pFtsdCtrl->irqConfig.pCmdCallback = FuncPtr;
pFtsdCtrl->irqConfig.pCmdArgs = Args;
break;
case FTSDCTRL_ERRORIRQID:
pFtsdCtrl->irqConfig.pErrorCallback = FuncPtr;
pFtsdCtrl->irqConfig.pErrorArgs = Args;
break;
default:
return FTSDC_FAILURE;
}
return FTSDC_SUCCESS;
}

View File

@ -0,0 +1,61 @@
/*
 * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
 *
 * SPDX-License-Identifier: Apache-2.0.
 *
* @Date: 2021-03-31 14:59:20
* @LastEditTime: 2021-05-25 16:47:05
* @Description:  This files is for sd ctrl option setting
*
* @Modify History: * * Ver   Who        Date         Changes
* ----- ------     --------    --------------------------------------
*/
#include "ft_sdctrl.h"
#include "ft_sdctrl_hw.h"
#include "ft_types.h"
#include "ft_io.h"
#include "ft_printf.h"
#include "ft_assert.h"
void FSdCtrl_NormalIrqSet(FtsdCtrl_t *pFtsdCtrl, FT_IN FSdCtrl_NormalIrqSelect_t flgs)
{
FSdCtrl_Config_t *pConfig;
u32 regValue;
Ft_assertVoid(FT_NULL != pFtsdCtrl);
pConfig = &pFtsdCtrl->config;
/* */
regValue = ((flgs & NORMAL_IRQ_CC) ? NORMAL_INT_EN_ECC : 0) | ((flgs & NORMAL_IRQ_CR) ? NORMAL_INT_EN_ECCRCE : 0) |
((flgs & NORMAL_IRQ_EI) ? NORMAL_INT_EN_ECIE : 0);
Ft_out32(pConfig->baseAddress + NORMAL_INT_EN_REG_OFFSET, regValue);
}
void FsdCtrl_errorIrqSet(FtsdCtrl_t *pFtsdCtrl, FT_IN FSdCtrl_ErrorIrqSelect_t flgs)
{
FSdCtrl_Config_t *pConfig;
u32 regValue;
Ft_assertVoid(FT_NULL != pFtsdCtrl);
pConfig = &pFtsdCtrl->config;
regValue = ((flgs & ERROR_IRQ_CTE) ? ERROR_INT_EN_CTE : 0) | ((flgs & ERROR_IRQ_CCRCE) ? ERROR_INT_EN_CCRCE : 0) |
((flgs & ERROR_IRQ_CIR) ? ERROR_INT_EN_CIR : 0) | ((flgs & ERROR_IRQ_CNR) ? ERROR_INT_EN_CNR : 0);
Ft_out32(pConfig->baseAddress + ERROR_INT_EN_REG_OFFSET, regValue);
}
void FSdCtrl_BdIrqSet(FtsdCtrl_t *pFtsdCtrl, FT_IN FSdCtrl_BdIrqSelect flgs)
{
FSdCtrl_Config_t *pConfig;
u32 regValue;
Ft_assertVoid(FT_NULL != pFtsdCtrl);
pConfig = &pFtsdCtrl->config;
regValue = ((flgs & BD_IRQ_TRS) ? BD_ISR_EN_ETRS : 0) | ((flgs & BD_IRQ_DTE) ? BD_ISR_EN_EDTE : 0) |
((flgs & BD_IRQ_CMDE) ? BD_ISR_EN_ECMDE : 0) | ((flgs & BD_IRQ_TRE) ? BD_ISR_EN_ETRE : 0) |
((flgs & BD_IRQ_NRCRC) ? BD_ISR_EN_ENRCRCE : 0) | ((flgs & BD_IRQ_DATFRAX) ? BD_ISR_EN_EDATFRAXE : 0) |
((flgs & BD_IRQ_RESPE) ? BD_ISR_EN_RESPE : 0) | ((flgs & BD_IRQ_DAIS) ? BD_ISR_EN_EDAISE : 0);
Ft_out32(pConfig->baseAddress + BD_ISR_EN_REG_OFFSET, regValue);
}

View File

@ -0,0 +1,33 @@
/*
 * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
 *
 * SPDX-License-Identifier: Apache-2.0.
 *
* @Date: 2021-03-31 14:59:20
* @LastEditTime: 2021-05-25 16:47:14
* @Description:  This files is for sd ctrl static initialization
*
* @Modify History: * * Ver   Who        Date         Changes
* ----- ------     --------    --------------------------------------
*/
#include "ft_sdctrl.h"
#include "ft_parameters.h"
extern FSdCtrl_Config_t FSdCtrl_Config[FT_SDC_NUM];
FSdCtrl_Config_t *FSdCtrl_LookupConfig(u32 instanceId)
{
FSdCtrl_Config_t *CfgPtr = NULL;
u32 Index;
for (Index = 0; Index < (u32)FT_GMAC_INSTANCES_NUM; Index++)
{
if (FSdCtrl_Config[Index].instanceId == instanceId)
{
CfgPtr = &FSdCtrl_Config[Index];
break;
}
}
return (FSdCtrl_Config_t *)CfgPtr;
}

View File

@ -0,0 +1,192 @@
/*
 * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
 *
 * SPDX-License-Identifier: Apache-2.0.
 *
* @Date: 2021-04-25 14:00:25
* @LastEditTime: 2021-05-24 14:34:28
* @Description:  This files is for
*
* @Modify History:
* Ver   Who        Date         Changes
* ----- ------     --------    --------------------------------------
*/
#include "ft_assert.h"
#include "ft_spi.h"
#include "ft_spi_hw.h"
#include "ft_generic_timer.h"
#include "ft_gpio.h"
void FSpi_DumpAllStatus(FT_IN FSpi_Ctrl_t *pCtrl, FT_IN char *tag)
{
FT_SPI_DEBUG_I("***%s status******\r\n", tag);
FT_SPI_DEBUG_I("busy: %d", SPI_STATUS_REG(pCtrl)->val.Busy);
FT_SPI_DEBUG_I("tx fifo not empty: %d", SPI_STATUS_REG(pCtrl)->val.Tfnf);
FT_SPI_DEBUG_I("tx fifo empty: %d", SPI_STATUS_REG(pCtrl)->val.Tfe);
FT_SPI_DEBUG_I("rx fifo not empty: %d", SPI_STATUS_REG(pCtrl)->val.Rfne);
FT_SPI_DEBUG_I("rx fifo full: %d", SPI_STATUS_REG(pCtrl)->val.Rff);
FT_SPI_DEBUG_I("trans error: %d", SPI_STATUS_REG(pCtrl)->val.Txe);
FT_SPI_DEBUG_I("trans conflict error: %d", SPI_STATUS_REG(pCtrl)->val.Dcol);
}
u32 FSpi_ReadWriteByte(FT_INOUT FSpi_Ctrl_t *pCtrl, FT_IN u8 TxData,
FT_OUT u8 *pRxData)
{
u32 Retry = 0;
u32 Ret = ERR_SPI_OK;
u16 RxData;
if (!pCtrl->IsReady)
{
return ERR_SPI_NOT_READY;
}
while (FSPI_TX_FIFO_NOT_EMPTY(pCtrl))
{
//Ft_GenericTimer_UsDelay(2);
if ((Retry++) > SPI_TIMEOUT)
{
Ret = ERR_SPI_TX_TIMEOUT;
goto __EXIT;
}
}
FSPI_WRITE_DATA(pCtrl, (u16)TxData);
Retry = 0;
while (FSPI_RX_FIFO_EMPTY(pCtrl))
{
//Ft_GenericTimer_UsDelay(2);
if ((Retry++) > SPI_TIMEOUT)
{
Ret = ERR_SPI_RX_TIMEOUT;
goto __EXIT;
}
}
RxData = FSPI_READ_DATA(pCtrl);
if (pRxData)
{
*pRxData = (u8)RxData;
}
__EXIT:
return Ret;
}
u32 FSpi_Init(FT_INOUT FSpi_Ctrl_t *pCtrl)
{
u32 Ret = ERR_SPI_OK;
FSPI_DISABLE(pCtrl);
/* config spi ctrl register */
SPI_CTRL0_REG(pCtrl)->val.Dfs = SPI_DFS_DEFAULT;
SPI_CTRL0_REG(pCtrl)->val.Frf = SPI_FRF_DEFAULT;
if (SPI_CTRL_CPHA_1EDGE == pCtrl->Config.Cpha)
{
SPI_CTRL0_REG(pCtrl)->val.Scph = SPI_SCPH_SW_CLK_AT_DATA_BEG;
}
else if (SPI_CTRL_CPHA_2EDGE == pCtrl->Config.Cpha)
{
SPI_CTRL0_REG(pCtrl)->val.Scph = SPI_SCPH_SW_CLK_AT_DATA_MID;
}
else
{
Ft_assertNoneReturn(0);
}
if (SPI_CTRL_CPOL_LOW == pCtrl->Config.Cpol)
{
SPI_CTRL0_REG(pCtrl)->val.Scpol = SPI_SCPOL_NOT_ACT_LOW;
}
else if (SPI_CTRL_CPOL_HIGH == pCtrl->Config.Cpol)
{
SPI_CTRL0_REG(pCtrl)->val.Scpol = SPI_SCPOL_NOT_ACT_HIGH;
}
else
{
Ft_assertNoneReturn(0);
}
SPI_CTRL0_REG(pCtrl)->val.Tmod = SPI_TMOD_TX_RX_MODE;
SPI_CTRL0_REG(pCtrl)->val.SlvOE = SPI_SLV_OE_DISABLE;
SPI_CTRL0_REG(pCtrl)->val.Srl = SPI_SRL_NORMAL_MODE;
SPI_CTRL0_REG(pCtrl)->val.Cfs = SPI_CFS_DEFAULT;
/* config spi clock */
FSPI_SET_BAUDR(pCtrl, pCtrl->Config.BaudRDiv);
/* config rx and tx fifo, fifo depth to trigger intr */
SPI_TXFTL_REG(pCtrl)->val.Tft = 0;
SPI_RXFTL_REG(pCtrl)->val.Rft = 0;
SPI_TXFL_REG(pCtrl)->val.Txtfl = 0;
SPI_RXFL_REG(pCtrl)->val.Rxtfl = 0;
SPI_RXSAMPLE_DLY_REG(pCtrl)->val.Rsd = SPI_DEFAULT_RSD;
FSPI_ENABLE(pCtrl);
/* set spi ready flag */
if (ERR_SPI_OK == Ret)
{
pCtrl->IsReady = TRUE;
}
return Ret;
}
static void FSpi_ToggleCSPin(FT_INOUT FSpi_Ctrl_t *pCtrl, FT_IN FSpi_DevId_t DevId,
FT_IN bool_t select)
{
u32 setVal = ((TRUE == select) ? GPIO_OFF : GPIO_ON);
Ft_assertNoneReturn(NULL != pCtrl);
if (FGpio_ReadPinA(GPIO_CTRL_ID_1, pCtrl->CsPin) != setVal)
{
FGpio_WritePinA(GPIO_CTRL_ID_1, pCtrl->CsPin, setVal);
}
Ft_GenericTimer_UsDelay(10);
return;
}
void FSpi_SelectSlave(FT_INOUT FSpi_Ctrl_t *pCtrl, FT_IN FSpi_DevId_t DevId,
FT_IN bool_t select)
{
FSpi_SeReg_t *pSelReg;
u32 setVal = ((TRUE == select) ? SPI_SE_SELECTED : SPI_SE_UNSELECTED);
FSPI_DISABLE(pCtrl);
/* enable or disable specific spi slave device */
pSelReg = SPI_SE_REG(pCtrl);
switch (DevId)
{
case SPI_DEV_ID_0:
pSelReg->val.SelSlave_0 = setVal;
break;
case SPI_DEV_ID_1:
pSelReg->val.SelSlave_1 = setVal;
Ft_assertNoneReturn(0);
break;
case SPI_DEV_ID_2:
pSelReg->val.SelSlave_2 = setVal;
Ft_assertNoneReturn(0);
break;
case SPI_DEV_ID_3:
pSelReg->val.SelSlave_3 = setVal;
Ft_assertNoneReturn(0);
break;
default:
Ft_assertNoneReturn(0);
break;
}
FSpi_ToggleCSPin(pCtrl, DevId, select);
FSPI_ENABLE(pCtrl);
return;
}

View File

@ -0,0 +1,95 @@
/*
 * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
 *
 * SPDX-License-Identifier: Apache-2.0.
 *
* @Date: 2021-04-25 13:59:05
* @LastEditTime: 2021-04-30 16:11:46
* @Description:  This files is for
*
* @Modify History:
* Ver   Who        Date         Changes
* ----- ------     --------    --------------------------------------
*/
#ifndef FT_BSP_SPI_H
#define FT_BSP_SPI_H
#ifdef __cplusplus
extern "C"
{
#endif
#include "ft_types.h"
#include "ft_spi_hw.h"
#include "ft_error_code.h"
#include "ft_debug.h"
typedef struct
{
u8 WorkMode;
#define SPI_CTRL_MASTER_MODE (u8)0x0
#define SPI_CTRL_SLAVE_MODE (u8)0x1
u8 DevAddrLen;
#define SPI_3_BYTE_ADDR (u8)0x3
#define SPI_4_BYTE_ADDR (u8)0x4
u8 Cpol;
#define SPI_CTRL_CPOL_LOW (u8)0x0
#define SPI_CTRL_CPOL_HIGH (u8)0x1
u8 Cpha;
#define SPI_CTRL_CPHA_1EDGE (u8)0x0
#define SPI_CTRL_CPHA_2EDGE (u8)0x1
u8 DevAddr[4];
u32 BaudRDiv;
} FSpi_Conf_t;
typedef struct
{
FSpi_Conf_t Config;
FSpi_CtrlId_t CtrlId;
FSpi_DevId_t DevId; /* support only one slave at the moment */
bool_t IsReady;
u16 CsPin; /* cs pin in gpio group A */
} FSpi_Ctrl_t;
/* misc marco */
#define SPI_TIMEOUT 5000
#define SPI_DUMMY_TX_DATA 0xFF
/* ctrl member shortcut */
#define FSPI_DEV_ADDR_LEN(pCtrl) (pCtrl->Config.DevAddrLen)
#define FSPI_IS_3_BYTE_ADDR(pCtrl) (SPI_3_BYTE_ADDR == FSPI_DEV_ADDR_LEN(pCtrl))
#define FSPI_DEV_ADDR(pCtrl) (pCtrl->Config.DevAddr)
/* define error code */
#define ERR_SPI_OK ERR_SUCCESS
#define ERR_SPI_GENERAL FT_CODE_ERR(ERR_MODE_SPI, 0, 1)
#define ERR_SPI_NOT_READY FT_CODE_ERR(ERR_MODE_SPI, 0, 2)
#define ERR_SPI_TX_TIMEOUT FT_CODE_ERR(ERR_MODE_SPI, 0, 3)
#define ERR_SPI_RX_TIMEOUT FT_CODE_ERR(ERR_MODE_SPI, 0, 4)
/* spi flash error code */
#define ERR_SPI_WAIT_TIMEOUT FT_CODE_ERR(ERR_MODE_SPI, 1, 1)
/* define debug utilities */
#define FT_SPI_DEBUG_TAG "FT_SPI"
#define FT_SPI_ENABLE_DEBUG
#define FT_SPI_ERROR(format, ...) FT_DEBUG_PRINT_E(FT_SPI_DEBUG_TAG, format, ##__VA_ARGS__)
#ifdef FT_SPI_ENABLE_DEBUG
#define FT_SPI_DEBUG_I(format, ...) FT_DEBUG_PRINT_I(FT_SPI_DEBUG_TAG, format, ##__VA_ARGS__)
#define FT_SPI_DEBUG_W(format, ...) FT_DEBUG_PRINT_W(FT_SPI_DEBUG_TAG, format, ##__VA_ARGS__)
#else
#define FT_SPI_DEBUG_I(format, ...)
#define FT_SPI_DEBUG_W(format, ...)
#endif
u32 FSpi_Init(FT_INOUT FSpi_Ctrl_t *pCtrl);
u32 FSpi_ReadWriteByte(FT_INOUT FSpi_Ctrl_t *pCtrl, FT_IN u8 TxData,
FT_OUT u8 *pRxData);
void FSpi_SelectSlave(FT_INOUT FSpi_Ctrl_t *pCtrl, FT_IN FSpi_DevId_t DevId,
FT_IN bool_t select);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,330 @@
/*
 * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
 *
 * SPDX-License-Identifier: Apache-2.0.
 *
* @Date: 2021-04-25 13:59:44
* @LastEditTime: 2021-04-30 15:42:30
* @Description:  This files is for
*
* @Modify History:
* Ver   Who        Date         Changes
* ----- ------     --------    --------------------------------------
*/
#ifndef FT_BSP_SPI_HW_H
#define FT_BSP_SPI_HW_H
#ifdef __cplusplus
extern "C"
{
#endif
#include "ft_types.h"
/* offset map of SPI register */
#define SPI_CTRL_R0 0x00 //Ctrl register 0
#define SPI_CTRL_R1 0x04 //Ctrl register 1
#define SPI_SSI_EN_R 0x08 //SPI enable register
#define SPI_MW_CR 0x0c //Microwire ctrl register
#define SPI_SE_R 0x10 //Slave enable register
#define SPI_BAUD_R 0x14 //Baudrate set register
#define SPI_TXFTL_R 0x18 //Tx threshold register
#define SPI_RXFTL_R 0x1c //Rx threshold register
#define SPI_TXFL_R 0x20 //Tx level register
#define SPI_RXFL_R 0x24 //Rx level register
#define SPI_S_R 0x28 //Status register
#define SPI_IM_R 0x2c //Intr mask register
#define SPI_RIS_R 0x34 //Intr status register
#define SPI_TXOI_CR 0x38 //TX FIFO overflow intr clear register
#define SPI_RXOI_CR 0x3c //RX FIFO overflow intr clear register
#define SPI_RXUI_CR 0x40 //TX FIFO underflow intr clear register
#define SPI_MSTI_CR 0x44 //Multi slave intr clear register
#define SPI_IC_R 0x48 //Intr clear register
#define SPI_DMA_CR 0x4c //DMA ctrl register
#define SPI_DMA_TDL_R 0x50 //DMA TX Data level register
#define SPI_DMA_RDL_R 0x54 //DMA RX Data level register
#define SPI_ID_R 0x58 //Identification register
#define SPI_D_R 0xec //Data register
#define SPI_RX_SAMPLE_DLY 0xfc //RX Data delay register
typedef enum
{
SPI_CTRL_ID_0 = 0,
SPI_CTRL_ID_1,
NUM_OF_SPI_CTRL,
} FSpi_CtrlId_t;
typedef enum
{
SPI_DEV_ID_0 = 0,
SPI_DEV_ID_1,
SPI_DEV_ID_2,
SPI_DEV_ID_3,
NUM_OF_SPI_DEV,
} FSpi_DevId_t;
/* base address of SPI register */
const static u32 g_SpiBaseAddr[NUM_OF_SPI_CTRL] = {0x2800c000, 0x28013000};
typedef union
{
u32 data;
struct
{
u32 Dfs : 4; /* 3:0, select data length */
#define SPI_DFS_DEFAULT 0x7
u32 Frf : 2; /* 5:4, selcet trans mode */
#define SPI_FRF_DEFAULT 0x0
u32 Scph : 1; /* 6, serial clock phase */
#define SPI_SCPH_SW_CLK_AT_DATA_MID 0x0 /* second edge */
#define SPI_SCPH_SW_CLK_AT_DATA_BEG 0x1 /* first edge */
u32 Scpol : 1; /* 7, serial clock Polarity */
#define SPI_SCPOL_NOT_ACT_LOW 0x0
#define SPI_SCPOL_NOT_ACT_HIGH 0x1
u32 Tmod : 2; /* 9:8, ctrl trans mode, indicate if tx rx data is valid */
#define SPI_TMOD_TX_RX_MODE 0x0
#define SPI_TMOD_TX_MODE 0x1
#define SPI_TMOD_RX_MODE 0x2
#define SPI_TMOD_EEPROM_MODE 0x3
u32 SlvOE : 1; /* 10, enable slave tx logic */
#define SPI_SLV_OE_ENABLE 0x0
#define SPI_SLV_OE_DISABLE 0x1
u32 Srl : 1; /* 11, shift register loopback */
#define SPI_SRL_NORMAL_MODE 0x0
#define SPI_SRL_TEST_MODE 0x1
u32 Cfs : 4; /* 15:12, ctrl data size, applied in Microwire mode */
#define SPI_CFS_DEFAULT 0x0
u32 Reserve : 16;
} val;
} FSpi_CtrlReg0_t;
typedef union
{
u32 data;
struct
{
u32 ndf : 16; /* 15:0 valid when TMOD = 10, TMOD = 11 */
#define SPI_NDF_DEFAULT 16
u32 Reserve : 16;
} val;
} FSpi_CtrlReg1_t;
typedef struct
{
u32 CPOL;
u32 CPHA;
} FSpi_ClockMode_t;
static const FSpi_ClockMode_t g_FSpi_ClockMode[4] =
{
{.CPOL = SPI_SCPOL_NOT_ACT_LOW, .CPHA = SPI_SCPH_SW_CLK_AT_DATA_BEG}, /* low level logic, sample at rising edge, shift at falling edge */
{.CPOL = SPI_SCPOL_NOT_ACT_LOW, .CPHA = SPI_SCPH_SW_CLK_AT_DATA_MID}, /* low level logic, sample at falling edge, shift at rising edge */
{.CPOL = SPI_SCPOL_NOT_ACT_HIGH, .CPHA = SPI_SCPH_SW_CLK_AT_DATA_MID}, /* high level logic, sample at falling edge, shift at rising edge */
{.CPOL = SPI_SCPOL_NOT_ACT_HIGH, .CPHA = SPI_SCPH_SW_CLK_AT_DATA_BEG}, /* high level logic, sample at rising edge, shift at falling edge */
};
typedef union
{
u32 data;
struct
{
u32 SsiEn : 1; /* 0, enable or disable all SPI op */
u32 Reserve : 31;
} val;
} FSpi_SsiEnReg_t;
typedef union
{
u32 data;
struct
{
u32 MwMod : 1; /* 0 microwire trans mode */
#define SPI_MWMODE_NO_CONTINUOUES 0
#define SPI_MWMODE_CONTINUOUES 1
u32 Mdd : 1; /* 1 microwire ctrl bit */
#define SPI_MWMDD_RXFROM_EXT_DEV 0
#define SPI_MWMDD_TXTO_EXT_DEV 1
u32 Mhs : 1; /* 2 microwire handshake */
#define SPI_MWMHS_DISABLE 0
#define SPI_MWMHS_ENABLE 1
u32 Reserve : 29;
} val;
} FSpi_MwcrReg_t;
typedef union
{
u32 data;
struct
{
u32 SelSlave_0 : 1; /* 3:0, select specifc slave device */
u32 SelSlave_1 : 1;
u32 SelSlave_2 : 1;
u32 SelSlave_3 : 1;
#define SPI_SE_SELECTED 0x1
#define SPI_SE_UNSELECTED 0x0
u32 Reserve : 28;
} val;
} FSpi_SeReg_t;
typedef union
{
u32 data;
struct
{
u32 Sckdv : 16; /* 15:0, SSI clk divider, must be times of 2 */
#define SPI_SCKDV_MIN (2)
#define SPI_SCKDV_4 (4)
#define SPI_SCKDV_8 (8)
#define SPI_SCKDV_16 (16)
#define SPI_SCKDV_32 (20)
#define SPI_SCKDV_64 (28)
#define SPI_SCKDV_128 (128)
#define SPI_SCKDV_256 (256)
#define SPI_SCKDV_1024 (1024)
#define SPI_SCKDV_4096 (4096)
#define SPI_SCKDV_12800 (12800)
#define SPI_SCKDV_56800 (56800)
#define SPI_SCKDV_MAX (65534)
u32 Reserve : 16;
} val;
} FSpi_BaudrReg_t;
typedef union
{
u32 data;
struct
{
u32 Tft : 8; /* 7:0, TX FIFO threshold */
u32 Reserve : 24;
} val;
} FSpi_TxFtlrReg_t;
typedef union
{
u32 data;
struct
{
u32 Rft : 8; /* 7:0, RX FIFO threshold */
u32 Reserve : 24;
} val;
} FSpi_RxFtlrReg_t;
typedef union
{
u32 data;
struct
{
u32 Txtfl : 8; /* 7:0, TX FIFO level, num of valid num */
u32 Reserve : 24;
} val;
} FSpi_TxFlrReg_t;
typedef union
{
u32 data;
struct
{
u32 Rxtfl : 8; /* 7:0, RX FIFO level, num of valid num */
u32 Reserve : 24;
} val;
} FSpi_RxFlrReg_t;
typedef union
{
u32 data;
struct
{
u32 Busy : 1; /* 0, SPI bus busy bit */
u32 Tfnf : 1; /* 1, tx FIFO not empty */
#define SPI_TX_FIFO_FULL 0x0
#define SPI_TX_FIFO_NOT_FULL 0x1
u32 Tfe : 1; /* 2, tx FIFO empty */
#define SPI_TX_FIFO_NOT_EMPTY 0x0
#define SPI_TX_FIFO_EMPTY 0x1
u32 Rfne : 1; /* 3, rx FIFO not emptu */
#define SPI_RX_FIFO_EMPTY 0x0
#define SPI_RX_FIFO_NOT_EMPTY 0x1
u32 Rff : 1; /* 4, rx FIFO full */
#define SPI_RX_FIFO_NOT_FULL 0x0
#define SPI_RX_FIFO_FULL 0x1
u32 Txe : 1; /* 5, trans error */
#define SPI_TX_NO_ERR 0x0
#define SPI_TX_ERR 0x1
u32 Dcol : 1; /* 6, trans conflict error */
#define SPI_TX_NO_COLERR 0x0
#define SPI_TX_COLERR 0x1
u32 Reserve : 25;
} val;
} FSpi_StatusReg_t; /* Read-Only */
typedef union
{
u32 IdCode : 32;
} FSpi_IDReg_t;
typedef union
{
u32 data;
struct
{
u32 Dr : 16; /* 15:0, RX and TX fifo */
#define SPI_8BIT_MASK 0xFF
#define SPI_16BIT_MASK 0xFFFF
u32 Reserve : 16;
} val;
} FSpi_DataReg_t;
typedef union
{
u32 data;
struct
{
u32 Rsd : 8; /* 7:0, RX data delay */
#define SPI_DEFAULT_RSD 0x6
u32 Reserve : 24;
} val;
} FSpi_RxSampleDlyReg_t;
#define SPI_CTL_ID(pCtrl) ((pCtrl)->CtrlId)
#define SPI_BASE_ADDR(pCtrl) (g_SpiBaseAddr[SPI_CTL_ID(pCtrl)])
/* select slave device */
#define SPI_SE_REG(pCtrl) ((FSpi_SeReg_t *)(SPI_BASE_ADDR(pCtrl) + SPI_SE_R))
/* set speed */
#define SPI_BAUDR_REG(pCtrl) ((FSpi_BaudrReg_t *)(SPI_BASE_ADDR(pCtrl) + SPI_BAUD_R))
#define FSPI_SET_BAUDR(pCtrl, div) (SPI_BAUDR_REG(pCtrl)->val.Sckdv = (div))
#define FSPI_GET_BAUDR(pCtrl) (SPI_BAUDR_REG(pCtrl)->val.Sckdv)
/* check status */
#define SPI_STATUS_REG(pCtrl) ((FSpi_StatusReg_t *)(SPI_BASE_ADDR(pCtrl) + SPI_S_R))
#define FSPI_TX_FIFO_NOT_EMPTY(pCtrl) (SPI_TX_FIFO_NOT_EMPTY == (SPI_STATUS_REG(pCtrl)->val.Tfe))
#define FSPI_RX_FIFO_EMPTY(pCtrl) (SPI_RX_FIFO_EMPTY == (SPI_STATUS_REG(pCtrl)->val.Rfne))
/* enable/disable spi bus */
#define SPI_SSIEN_REG(pCtrl) ((FSpi_SsiEnReg_t *)(SPI_BASE_ADDR(pCtrl) + SPI_SSI_EN_R))
#define FSPI_ENABLE(pCtrl) (SPI_SSIEN_REG(pCtrl)->val.SsiEn = 1)
#define FSPI_DISABLE(pCtrl) (SPI_SSIEN_REG(pCtrl)->val.SsiEn = 0)
/* shortcut to access register */
#define SPI_CTRL0_REG(pCtrl) ((FSpi_CtrlReg0_t *)(SPI_BASE_ADDR(pCtrl) + SPI_CTRL_R0))
#define SPI_CTRL1_REG(pCtrl) ((FSpi_CtrlReg1_t *)(SPI_BASE_ADDR(pCtrl) + SPI_CTRL_R1))
#define SPI_TXFTL_REG(pCtrl) ((FSpi_TxFtlrReg_t *)(SPI_BASE_ADDR(pCtrl) + SPI_TXFTL_R))
#define SPI_RXFTL_REG(pCtrl) ((FSpi_RxFtlrReg_t *)(SPI_BASE_ADDR(pCtrl) + SPI_RXFTL_R))
#define SPI_TXFL_REG(pCtrl) ((FSpi_TxFlrReg_t *)(SPI_BASE_ADDR(pCtrl) + SPI_TXFL_R))
#define SPI_RXFL_REG(pCtrl) ((FSpi_RxFlrReg_t *)(SPI_BASE_ADDR(pCtrl) + SPI_RXFL_R))
#define SPI_ID_REG(pCtrl) ((FSpi_IDReg_t *)(SPI_BASE_ADDR(pCtrl) + SPI_ID_R))
#define FSPI_GET_ID(pCtrl) (SPI_ID_REG(pCtrl)->IdCode)
#define SPI_DATA_REG(pCtrl) ((FSpi_DataReg_t *)(SPI_BASE_ADDR(pCtrl) + SPI_D_R))
#define FSPI_READ_DATA(pCtrl) (u16)(SPI_DATA_REG(pCtrl)->val.Dr)
#define FSPI_WRITE_DATA(pCtrl, dat) (SPI_DATA_REG(pCtrl)->val.Dr = (u16)(dat))
#define SPI_RXSAMPLE_DLY_REG(pCtrl) ((FSpi_RxSampleDlyReg_t *)(SPI_BASE_ADDR(pCtrl) + SPI_RX_SAMPLE_DLY))
#define SPI_MWCTRL_REG(pCtrl) ((FSpi_MwcrReg_t *)SPI_BASE_ADDR(pCtrl) + SPI_MW_CR)
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,13 @@
/*
 * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
 *
 * SPDX-License-Identifier: Apache-2.0.
 *
* @Date: 2021-04-25 14:00:39
* @LastEditTime: 2021-04-25 14:00:39
* @Description:  This files is for
*
* @Modify History:
* Ver   Who        Date         Changes
* ----- ------     --------    --------------------------------------
*/

View File

@ -0,0 +1,329 @@
/*
 * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
 *
 * SPDX-License-Identifier: Apache-2.0.
 *
* @Date: 2021-04-07 09:53:07
* @LastEditTime: 2021-05-24 10:48:22
* @Description:  This files is for uart functions
*
* @Modify History:
* Ver   Who        Date         Changes
* ----- ------     --------    --------------------------------------
*/
/***************************** Include Files ********************************/
#include "ft_status.h"
#include "ft_uart.h"
#include "ft_io.h"
#include "ft_error_code.h"
u32 FUart_SendBuffer(Ft_Uart *UartPtr);
u32 FUart_ReceiveBuffer(Ft_Uart *UartPtr);
static void FUart_StubHandler(void *Args, u32 Event,
u32 ByteCount);
/**
* @name: FUart_CfgInitialize
* @msg: initalize uart configure
* @return {*}
* @param {Ft_Uart} *UartPtr
* @param {FUart_Config_t} *Config
*/
s32 FUart_CfgInitialize(Ft_Uart *UartPtr, FUart_Config_t *Config)
{
u32 RegValue = 0;
Ft_assertNonvoid(UartPtr != NULL);
Ft_assertNonvoid(Config != NULL);
UartPtr->Config.InstanceId = Config->InstanceId;
UartPtr->Config.BaseAddress = Config->BaseAddress;
UartPtr->Config.RefClockHz = Config->RefClockHz;
UartPtr->Config.IsrNum = Config->IsrNum;
UartPtr->Handler = FUart_StubHandler;
UartPtr->SendBuffer.BytePtr = NULL;
UartPtr->SendBuffer.RequestedBytes = 0;
UartPtr->SendBuffer.RemainingBytes = 0;
UartPtr->ReceiveBuffer.BytePtr = NULL;
UartPtr->ReceiveBuffer.RequestedBytes = 0;
UartPtr->ReceiveBuffer.RemainingBytes = 0;
UartPtr->rxbs_error = 0;
UartPtr->IsReady = FT_COMPONENT_IS_READLY;
//<! 设置波特率
/*
* Set up the default data format: 8 bit data, 1 stop bit, no
* parity
*/
RegValue = ((FUART_FORMAT_WORDLENGTH_8BIT << 5) & UARTLCR_H_WLEN); //<! 8bit word length
RegValue |= (0 << 3) & UARTLCR_H_STP2; //<! 1 stopbit
RegValue |= (0 << 1) & UARTLCR_H_PEN; //<! no parity
RegValue |= (1 << 4) & UARTLCR_H_FEN; //<! fifo en
FT_UART_WriteReg(UartPtr->Config.BaseAddress, UARTLCR_H_OFFSET, RegValue);
/* Set the RX FIFO trigger at 8 data bytes.Tx FIFO trigger is 8 data bytes*/
RegValue = (1 << 3) | (1 << 0);
FT_UART_WriteReg(UartPtr->Config.BaseAddress, UARTIFLS_OFFSET, RegValue);
/* Disable all interrupts, polled mode is the default */
RegValue = 0;
FT_UART_WriteReg(UartPtr->Config.BaseAddress, UARTIMSC_OFFSET, RegValue);
return FST_SUCCESS;
}
/**
* @name: FUart_Send
* @msg:
* @param {Ft_Uart} *UartPtr
* @param {u8} *Buffer
* @param {u32} Length
* @return {u32} The Number of bytes actully sent.
*/
u32 FUart_Send(Ft_Uart *UartPtr, u8 *BytePtr, u32 Length)
{
u32 RegValue = 0;
u32 SentCount = 0;
Ft_assertNonvoid(UartPtr != NULL);
Ft_assertNonvoid(BytePtr != NULL);
Ft_assertNonvoid(UartPtr->IsReady == FT_COMPONENT_IS_READLY);
/*
* Disable the UART transmit interrupts to allow this call to stop a
* previous operation that may be interrupt driven.
*/
RegValue = FT_UART_ReadReg(UartPtr->Config.BaseAddress, UARTIMSC_OFFSET);
RegValue &= ~(UARTIMSC_TXIM);
FT_UART_WriteReg(UartPtr->Config.BaseAddress, UARTIMSC_OFFSET, RegValue);
UartPtr->SendBuffer.BytePtr = BytePtr;
UartPtr->SendBuffer.RequestedBytes = Length;
UartPtr->SendBuffer.RemainingBytes = Length;
SentCount = FUart_SendBuffer(UartPtr);
return SentCount;
}
/**
* @name: FUart_PutChar
* @msg: send a char through uart
* @return {*}
* @param {Ft_Uart} *UartPtr
* @param {s8} Data
*/
void FUart_PutChar(Ft_Uart *UartPtr, s8 Data)
{
Ft_assertVoid(UartPtr != NULL);
Ft_assertVoid(UartPtr->IsReady == FT_COMPONENT_IS_READLY);
while (!FT_UART_IsTransmitFull(UartPtr->Config.BaseAddress))
{
FT_UART_WriteReg(UartPtr->Config.BaseAddress, UARTDR_OFFSET, Data);
break;
}
}
static void FUart_StubHandler(void *Args, u32 Event,
u32 ByteCount)
{
(void)Args;
(void)Event;
(void)ByteCount;
Ft_assertVoidAlways();
}
/**
* @name: FUart_SendBuffer
* @msg: send data buffer through uart
* @return {*}
* @param {Ft_Uart} *UartPtr
*/
u32 FUart_SendBuffer(Ft_Uart *UartPtr)
{
u32 SentCount = 0U;
u32 RegValue;
/*
* If the TX FIFO is full, send nothing.
* Otherwise put bytes into the TX FIFO unil it is full, or all of the
* data has been put into the FIFO.
*/
while ((!FT_UART_IsTransmitFull(UartPtr->Config.BaseAddress)) && (UartPtr->SendBuffer.RemainingBytes > SentCount))
{
FT_UART_WriteReg(UartPtr->Config.BaseAddress, UARTDR_OFFSET, (u32)UartPtr->SendBuffer.BytePtr[SentCount]);
SentCount++;
}
/* Update the buffer to reflect the bytes that were sent from it */
UartPtr->SendBuffer.BytePtr += SentCount;
UartPtr->SendBuffer.RemainingBytes -= SentCount;
RegValue = FT_UART_ReadReg(UartPtr->Config.BaseAddress, UARTIMSC_OFFSET);
RegValue |= (UARTIMSC_TXIM);
FT_UART_WriteReg(UartPtr->Config.BaseAddress, UARTIMSC_OFFSET, RegValue);
return SentCount;
}
/**
* @name: FUart_Receive
* @msg: receive data through uart
* @return {*}
* @param {Ft_Uart} *UartPtr
* @param {u8} *BytePtr
* @param {u32} Length
*/
u32 FUart_Receive(Ft_Uart *UartPtr, u8 *BytePtr, u32 Length)
{
u32 Received;
u32 BackRegValue;
Ft_assertNonvoid(UartPtr != NULL);
Ft_assertNonvoid(BytePtr != NULL);
Ft_assertNonvoid(UartPtr->IsReady == FT_COMPONENT_IS_READLY);
/*
* Disable all the interrupts.
* This stops a previous operation that may be interrupt driven
*/
BackRegValue = FT_UART_ReadReg(UartPtr->Config.BaseAddress, UARTIMSC_OFFSET);
FT_UART_WriteReg(UartPtr->Config.BaseAddress, UARTIMSC_OFFSET, 0);
UartPtr->ReceiveBuffer.BytePtr = BytePtr;
UartPtr->ReceiveBuffer.RequestedBytes = Length;
UartPtr->ReceiveBuffer.RemainingBytes = Length;
Received = FUart_ReceiveBuffer(UartPtr);
FT_UART_WriteReg(UartPtr->Config.BaseAddress, UARTIMSC_OFFSET, BackRegValue);
return Received;
}
/**
* @name: Ft_Uart_ReceiveBuffer
* @msg: handling uart receive buffer
* @return {*}
* @param {Ft_Uart} *UartPtr
*/
u32 FUart_ReceiveBuffer(Ft_Uart *UartPtr)
{
u32 ReceivedCount = 0U;
u32 Event;
u32 EventData;
u32 ByteValue;
while ((ReceivedCount < UartPtr->ReceiveBuffer.RemainingBytes) && !FT_UART_IsReceiveData(UartPtr->Config.BaseAddress))
{
ByteValue = FT_UART_ReadReg(UartPtr->Config.BaseAddress, UARTDR_OFFSET);
if (UartPtr->rxbs_error)
{
if ((ByteValue & UARTDR_ALLE) != 0)
{
EventData = ByteValue;
Event = FUART_EVENT_PARE_FRAME_BRKE;
if (UartPtr->Handler)
{
UartPtr->Handler(UartPtr->Args, Event, EventData);
}
}
}
UartPtr->ReceiveBuffer.BytePtr[ReceivedCount] = (u8)(ByteValue & 0xff);
ReceivedCount++;
}
UartPtr->rxbs_error = 0;
if (UartPtr->ReceiveBuffer.BytePtr != NULL)
{
UartPtr->ReceiveBuffer.BytePtr += ReceivedCount;
}
UartPtr->ReceiveBuffer.RemainingBytes -= ReceivedCount;
return ReceivedCount;
}
/**
* @name: FUart_BlockSend
* @msg: initiate uart block send
* @return {*}
* @param {Ft_Uart} *UartPtr
* @param {u8} *BytePtr
* @param {u32} Length
*/
void FUart_BlockSend(Ft_Uart *UartPtr, u8 *BytePtr, u32 Length)
{
u32 index;
Ft_assertVoid(UartPtr != NULL);
Ft_assertVoid(BytePtr != NULL);
Ft_assertVoid(UartPtr->IsReady == FT_COMPONENT_IS_READLY);
for (index = 0; index < Length; index++)
{
FUart_SendByte(UartPtr->Config.BaseAddress, BytePtr[index]);
}
}
/**
* @name: FUart_BlockReceive
* @msg: initiate uart block receive
* @return {*}
* @param {Ft_Uart} *UartPtr
*/
u8 FUart_BlockReceive(Ft_Uart *UartPtr)
{
Ft_assertNonvoid(UartPtr != NULL);
Ft_assertNonvoid(UartPtr->IsReady == FT_COMPONENT_IS_READLY);
return FUart_RecvByte(UartPtr->Config.BaseAddress);
}
/**
* @name: FUart_SetBaudRate
* @msg: set baudrate of UART trans
* @return {*}
* @param {Ft_Uart} *UartPtr
* @param {u32} BaudRate
*/
u32 FUart_SetBaudRate(Ft_Uart *UartPtr, u32 BaudRate)
{
u32 temp;
u32 divider;
u32 remainder;
u32 fraction;
Ft_assertNonvoid(NULL != UartPtr);
if ((BaudRate * 2) > UartPtr->Config.RefClockHz)
{
return ERR_INPUT_BAUD_NO_SUPPORT;
}
/* calculate baud rate divisor */
temp = 16 * BaudRate;
divider = UartPtr->Config.RefClockHz / temp;
remainder = UartPtr->Config.RefClockHz % temp;
temp = (128 * remainder) / temp;
fraction = temp / 2;
if (0 != (temp & 1))
{
fraction++;
}
FUart_ClearSpecificOptions(UartPtr, FUART_OPTION_RXEN | FUART_OPTION_TXEN);
/* set baud register */
FT_UART_WriteReg(UartPtr->Config.BaseAddress, UARTIBRD_OFFSET, divider);
FT_UART_WriteReg(UartPtr->Config.BaseAddress, UARTFBRD_OFFSET, fraction);
FUart_SetSpecificOptions(UartPtr, FUART_OPTION_RXEN | FUART_OPTION_TXEN);
return ERR_SUCCESS;
}

View File

@ -0,0 +1,120 @@
/*
 * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
 *
 * SPDX-License-Identifier: Apache-2.0.
 *
* @Date: 2021-04-07 09:53:07
* @LastEditTime: 2021-05-24 10:13:51
* @Description:  This files is for uart functions
*
* @Modify History:
* Ver   Who        Date         Changes
* ----- ------     --------    --------------------------------------
*/
#ifndef FT_UART_H
#define FT_UART_H
#include "ft_types.h"
#include "ft_assert.h"
#include "ft_status.h"
#include "ft_uart_hw.h"
#define FUART_BAUDRATE 115200U
/* Config options */
#define FUART_OPTION_UARTEN 0x1U
#define FUART_OPTION_RXEN 0x2U
#define FUART_OPTION_TXEN 0x4U
#define FUART_OPTION_FIFOEN 0x8U
/* Data format values */
#define FUART_FORMAT_WORDLENGTH_8BIT 0x3
#define FUART_FORMAT_WORDLENGTH_7BIT 0x2
#define FUART_FORMAT_WORDLENGTH_6BIT 0x1
#define FUART_FORMAT_WORDLENGTH_5BIT 0x0
#define FUART_FORMAT_NO_PARITY 0U
#define FUART_FORMAT_MARK_PARITY 1U
#define FUART_FORMAT_SPACE_PARITY 2U
#define FUART_FORMAT_ODD_PARTY 3U
#define FUART_FORMAT_EVEN_PARITY 4U
#define FUART_FORMAT_2_STOP_BIT 0U
#define FUART_FORMAT_1_STOP_BIT 1U
/* Callback events */
#define FUART_EVENT_RECV_DATA 1U /**< Data receiving done */
#define FUART_EVENT_RECV_TOUT 2U /**< A receive timeout occurred */
#define FUART_EVENT_SENT_DATA 3U /**< Data transmission done */
#define FUART_EVENT_RECV_ERROR 4U /**< A receive error detected */
#define FUART_EVENT_MODEM 5U /**< Modem status changed */
#define FUART_EVENT_PARE_FRAME_BRKE 6U /**< A receive parity, frame, break \
* error detected */
#define FUART_EVENT_RECV_ORERR 7U /**< A receive overrun error detected */
/**************************** Type Definitions ******************************/
typedef struct
{
u32 InstanceId; /* Id of device*/
u32 BaseAddress;
u32 RefClockHz;
u32 IsrNum;
} FUart_Config_t;
typedef struct
{
u8 *BytePtr;
u32 RequestedBytes;
u32 RemainingBytes;
} FUart_Buffer_t;
typedef struct
{
u32 BaudRate; /**< In bps, ie 1200 */
u32 DataBits; /**< Number of data bits */
u32 Parity; /**< Parity */
u8 StopBits; /**< Number of stop bits */
} FUart_Format_t;
typedef void (*FUart_Handler_t)(void *Args, u32 Event, u32 EventData);
typedef struct
{
FUart_Config_t Config; /* Configuration data structure */
u32 InputClockHz;
u32 IsReady; /* Device is ininitialized and ready*/
u32 BaudRate;
FUart_Buffer_t SendBuffer;
FUart_Buffer_t ReceiveBuffer;
FUart_Handler_t Handler;
void *Args;
uint8_t rxbs_error; /* 接收过程中出现错误 0 无错误1 存在错误*/
} Ft_Uart;
/* define SD MMC error code */
typedef enum
{
ERR_SUB_MODE_UART_GENERAL = 0
} FT_UART_ERR_SUB_MODE;
#define ERR_INPUT_BAUD_NO_SUPPORT FT_CODE_ERR(ERR_MODE_UART, ERR_SUB_MODE_UART_GENERAL, 0x1)
void FUart_PutChar(Ft_Uart *UartPtr, s8 Data);
u32 FUart_Send(Ft_Uart *UartPtr, u8 *Buffer, u32 Length);
u32 FUart_Receive(Ft_Uart *UartPtr, u8 *BytePtr, u32 Length);
s32 FUart_CfgInitialize(Ft_Uart *UartPtr, FUart_Config_t *Config);
FUart_Config_t *FUart_LookupConfig(u32 InstanceId);
void FUart_SetOptions(Ft_Uart *UartPtr, u32 Options);
void FUart_SetSpecificOptions(Ft_Uart *UartPtr, u32 Options);
void FUart_ClearSpecificOptions(Ft_Uart *UartPtr, u32 Options);
void FUart_InterruptHandler(Ft_Uart *UartPtr);
void FUart_SetHandler(Ft_Uart *UartPtr, FUart_Handler_t FuncPtr,
void *Args);
void FUart_SetInterruptMask(Ft_Uart *UartPtr, u32 Mask);
u32 FUart_SetBaudRate(Ft_Uart *UartPtr, u32 BaudRate);
#endif // !

View File

@ -0,0 +1,34 @@
/*
 * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
 *
 * SPDX-License-Identifier: Apache-2.0.
 *
* @Date: 2021-04-07 09:53:07
* @LastEditTime: 2021-04-07 13:42:30
* @Description:  This files is for uart config
*
* @Modify History:
* Ver   Who        Date         Changes
* ----- ------     --------    --------------------------------------
*/
#include "ft_uart.h"
#include "ft_parameters.h"
FUart_Config_t FUart_Config_tTable[FT_UART_NUM] = {
{FT_UART0_ID,
FT_UART0_BASE_ADDR,
FT_UART0_CLK_FREQ_HZ,
38},
{FT_UART1_ID,
FT_UART1_BASE_ADDR,
FT_UART1_CLK_FREQ_HZ,
39},
{FT_UART2_ID,
FT_UART2_BASE_ADDR,
FT_UART2_CLK_FREQ_HZ,
40},
{FT_UART3_ID,
FT_UART3_BASE_ADDR,
FT_UART3_CLK_FREQ_HZ,
41}};

View File

@ -0,0 +1,46 @@
/*
 * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
 *
 * SPDX-License-Identifier: Apache-2.0.
 *
* @Date: 2021-04-07 09:53:07
* @LastEditTime: 2021-05-25 16:49:30
* @Description:  This files is for uart register function
*
* @Modify History:
* Ver   Who        Date         Changes
* ----- ------     --------    --------------------------------------
*/
#include "ft_uart_hw.h"
void FUart_SendByte(u32 BaseAddress, u8 Byte)
{
while (FT_UART_IsTransmitFull(BaseAddress))
{
;
}
FT_UART_WriteReg(BaseAddress, UARTDR_OFFSET, (u32)Byte);
}
u8 FUart_RecvByte(u32 BaseAddress)
{
u32 RecievedByte;
while (FT_UART_IsReceiveData(BaseAddress))
{
;
}
RecievedByte = FT_UART_ReadReg(BaseAddress, UARTDR_OFFSET);
return RecievedByte;
}
u8 FUart_GetChar(u32 BaseAddress)
{
u32 RecievedByte;
if (FT_UART_IsReceiveData(BaseAddress))
{
return 0xff;
}
RecievedByte = FT_UART_ReadReg(BaseAddress, UARTDR_OFFSET);
return RecievedByte;
}

View File

@ -0,0 +1,221 @@
/*
 * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
 *
 * SPDX-License-Identifier: Apache-2.0.
 *
* @Date: 2021-03-31 14:59:20
* @LastEditTime: 2021-04-02 14:14:34
* @Description:  This files is for definition of uart register
*
* @Modify History: * * Ver   Who        Date         Changes
* ----- ------     --------    --------------------------------------
*/
#ifndef FT_UART_HW_H
#define FT_UART_HW_H
#ifdef __cplusplus
extern "C"
{
#endif
#include "ft_types.h"
#include "ft_assert.h"
#include "ft_io.h"
/************************** Constant Definitions *****************************/
/** @name Register Map
*
* Register offsets for the UART.
* @{
*/
#define UARTDR_OFFSET 0U /* 数据寄存器 */
#define UARTRSR_OFFSET 4U /* 接收状态寄存器/错误清除寄存器 */
#define UARTECR_OFFSET UARTRSR_OFFSET
#define UARTFTR_OFFSET 0x18U /* 标志寄存器 */
#define UARTILPR_OFFSET 0x020U /* 低功耗计数寄存器 */
#define UARTIBRD_OFFSET 0x024U /* 波特率整数值配置寄存器 */
#define UARTFBRD_OFFSET 0x028U /* 波特率小数值配置寄存器 */
#define UARTLCR_H_OFFSET 0x02cU /* 线控寄存器 */
#define UARTCR_OFFSET 0x030U /* 控制寄存器 */
#define UARTIFLS_OFFSET 0x034U /* FIFO阈值选择寄存器 */
#define UARTIMSC_OFFSET 0x038U /* 中断屏蔽选择清除寄存器 */
#define UARTRIS_OFFSET 0x03cU /* 中断状态寄存器 */
#define UARTMIS_OFFSET 0x040U /* 中断屏蔽状态寄存器 */
#define UARTICR_OFFSET 0x044U /* 中断清除寄存器 */
#define UARTDMACR_OFFSET 0x048U /* DMA控制寄存器 */
/* 数据寄存器 RW */
#define UARTDR_OE 0x800U /* 如果接收到数据并且接收的 FIFO 已满,该位设置为 1 */
#define UARTDR_BE 0x400U /* 突发错误 */
#define UARTDR_PE 0x200U /* 奇偶校验错误。 */
#define UARTDR_FE 0x100U /* 帧错误。 */
#define UARTDR_ALLE (UARTDR_OE | UARTDR_BE | UARTDR_PE | UARTDR_FE)
#define UARTDR_DATA 0xffU /* R 接收数据 W 传输数据 */
/* 接收状态寄存器 RW */
#define UARTRSR_OE 0x8U /* 溢出错误。 */
#define UARTRSR_BE 0x4U /* 突发错误 */
#define UARTRSR_PE 0x2U /* 奇偶校验错误。 */
#define UARTRSR_FE 0x1U /* 帧错误 */
#define UARTECR_CLE 0xffU /* 清除 */
/* 标志寄存器 RO */
#define UARTFTR_RI 0x100U /* Ring indicator */
#define UARTFTR_TXFE 0x80U /* Transmit FIFO empty */
#define UARTFTR_RXFF 0x40U /* Receive FIFO full */
#define UARTFTR_TXFF 0x20U /* Transmit FIFO full. */
#define UARTFTR_RXFE 0x10U /* Receive FIFO empty */
#define UARTFTR_BUSY 0x08U /* UART busy */
#define UARTFTR_DCD 0x04U /* Data carrier detect. */
#define UARTFTR_DSR 0x02U /* Data set ready. */
#define UARTFTR_CTS 0x1U /* Clear to send */
/* IrDA 低功耗计数寄存器 RW */
#define UARTILPR_ILPDVSR 0xffU /* 8-bit low-power divisor value. These bits are cleared to 0 at reset */
/* 波特率整数值配置寄存器 RW */
#define UARTIBRD_BAUD_DIVFRAC 0xffffU /* The fractional baud rate divisor. */
/* 波特率小数值配置寄存器 RW */
#define UARTFBRD_BAUD_DIVFRAC 0x3fU /* The fractional baud rate divisor. */
/* 线控寄存器 RW */
#define UARTLCR_H_SPS 0x80U /* Stick parity select. */
#define UARTLCR_H_WLEN 0x60U /* Word length. */
#define UARTLCR_H_FEN 0x10U /* Enable FIFOs. */
#define UARTLCR_H_STP2 0x08U /* Two stop bits select. */
#define UARTLCR_H_EPS 0x04U /* Even parity select. */
#define UARTLCR_H_PEN 0x02U /* Parity enable. */
#define UARTLCR_H_BRK 0x01U /* send break */
/* 控制寄存器 RW */
#define UARTCR_CTSEN 0x8000U /* CTS hardware flow control enable. */
#define UARTCR_RTSEN 0x4000U /* RTS hardware flow control enable. */
#define UARTCR_OUT2 0x2000U /* This bit is the complement of the UART Out2 (nUARTOut2) modem status output. */
#define UARTCR_Out1 0x1000U /* This bit is the complement of the UART Out1 (nUARTOut1) modem status output. */
#define UARTCR_RTS 0x0800U /* Request to send. */
#define UARTCR_DTR 0x0400U /* Data transmit ready */
#define UARTCR_RXE 0x0200U /* Receive enable. */
#define UARTCR_TXE 0x0100U /* Transmit enable. */
#define UARTCR_LBE 0x0080U /* Loop back enable.*/
#define UARTCR_SIRLP 0x4U /* IrDA SIR low power mode. */
#define UARTCR_SIREN 0x2U /* SIR enable. */
#define UARTCR_UARTEN 0x1U /* UART enable. */
/* FIFO阈值选择寄存器 RW */
#define UARTIFLS_RXIFLSEL 0x38U /* Receive interrupt FIFO level select. */
#define UARTIFLS_TXIFLSEL 0x7U /* Transmit interrupt FIFO level select. */
/* 中断屏蔽选择清除寄存器 RW */
#define UARTIMSC_OEIM 0x400U /* Overrun error interrupt mask. */
#define UARTIMSC_BEIM 0x200U /* Break error interrupt mask */
#define UARTIMSC_PEIM 0x100U /* Parity error interrupt mask. */
#define UARTIMSC_FEIM 0x80U /* Framing error interrupt mask. */
#define UARTIMSC_RTIM 0x40U /* Receive timeout interrupt mask. */
#define UARTIMSC_TXIM 0x20U /* Transmit interrupt mask. */
#define UARTIMSC_RXIM 0x10U /* Receive interrupt mask. */
#define UARTIMSC_DSRMIM 0x8U /* nUARTDSR modem interrupt mask. */
#define UARTIMSC_DCDMIM 0x4U /* nUARTDCD modem interrupt mask. */
#define UARTIMSC_CTSMIM 0x2U /* nUARTCTS modem interrupt mask. */
#define UARTIMSC_RIMIM 0x1U /* nUARTRI modem interrupt mask. */
#define UARTIMSC_ALLM 0x3ffU /* all interrupt mask */
/* 中断状态寄存器 RO */
#define UARTRIS_OEIS 0x400U /* Overrun error interrupt mask. */
#define UARTRIS_BEIS 0x200U /* Break error interrupt mask */
#define UARTRIS_PEIS 0x100U /* Parity error interrupt mask. */
#define UARTRIS_FEIS 0x80U /* Framing error interrupt mask. */
#define UARTRIS_RTIS 0x40U /* Receive timeout interrupt mask. */
#define UARTRIS_TXIS 0x20U /* Transmit interrupt mask. */
#define UARTRIS_RXIS 0x10U /* Receive interrupt mask. */
#define UARTRIS_DSRMIS 0x8U /* nUARTDSR modem interrupt mask. */
#define UARTRIS_DCDMIS 0x4U /* nUARTDCD modem interrupt mask. */
#define UARTRIS_CTSMIS 0x2U /* nUARTCTS modem interrupt mask. */
#define UARTRIS_RIMIS 0x1U /* nUARTRI modem interrupt mask. */
/* 中断屏蔽状态寄存器 R0 */
#define UARTMIS_OEMIS 0x400U /* Overrun error interrupt mask. */
#define UARTMIS_BEMIS 0x200U /* Break error interrupt mask */
#define UARTMIS_PEMIS 0x100U /* Parity error interrupt mask. */
#define UARTMIS_FEMIS 0x80U /* Framing error interrupt mask. */
#define UARTMIS_RTMIS 0x40U /* Receive timeout interrupt mask. */
#define UARTMIS_TXMIS 0x20U /* Transmit interrupt mask. */
#define UARTMIS_RXMIS 0x10U /* Receive interrupt mask. */
#define UARTMIS_DSRMMIS 0x8U /* nUARTDSR modem interrupt mask. */
#define UARTMIS_DCDMMIS 0x4U /* nUARTDCD modem interrupt mask. */
#define UARTMIS_CTSMMIS 0x2U /* nUARTCTS modem interrupt mask. */
#define UARTMIS_RIMMIS 0x1U /* nUARTRI modem interrupt mask. */
/* 中断清除寄存器 WO */
#define UARTICR_OEIC 0x400U /* Overrun error interrupt mask. */
#define UARTICR_BEIC 0x200U /* Break error interrupt mask */
#define UARTICR_PEIC 0x100U /* Parity error interrupt mask. */
#define UARTICR_FEIC 0x80U /* Framing error interrupt mask. */
#define UARTICR_RTIC 0x40U /* Receive timeout interrupt mask. */
#define UARTICR_TXIC 0x20U /* Transmit interrupt mask. */
#define UARTICR_RXIC 0x10U /* Receive interrupt mask. */
#define UARTICR_DSRMIC 0x8U /* nUARTDSR modem interrupt mask. */
#define UARTICR_DCDMIC 0x4U /* nUARTDCD modem interrupt mask. */
#define UARTICR_CTSMIC 0x2U /* nUARTCTS modem interrupt mask. */
#define UARTICR_RIMIC 0x1U /* nUARTRI modem interrupt mask. */
/* DMA控制寄存器 RW */
#define UARTDMACR_DMAONERR 0x4U /* DMA on error. */
#define UARTDMACR_TXDMAE 0x2U /* Transmit DMA enable. */
#define UARTDMACR_RXDMAE 0x1U /* Receive DMA enable. */
/***************** Macros (Inline Functions) Definitions *********************/
/**
* @name: FT_UART_ReadReg
* @msg:
* @param {u32} BaseAddress
* @param {u32} RegOffset
* @return {u32}
*/
#define FT_UART_ReadReg(BaseAddress, RegOffset) Ft_in32(BaseAddress + (u32)RegOffset)
/**
* @name: FT_UART_WriteReg
* @msg:
* @param {u32} BaseAddress
* @param {u32} RegOffset
* @param {u32} RegisterValue
* @return {void}
*/
#define FT_UART_WriteReg(BaseAddress, RegOffset, RegisterValue) Ft_out32(BaseAddress + (u32)RegOffset, (u32)RegisterValue)
/**
* @name: FT_UART_ISRECEIVEDATA
* @msg:
* @param {u32} BaseAddress
* @return {bool} true false
*
*/
#define FT_UART_IsReceiveData(BaseAddress) (Ft_in32(BaseAddress + UARTFTR_OFFSET) & UARTFTR_RXFE)
/**
* @name: FT_UART_ISTRANSMITFULL
* @msg:
* @param {u32} BaseAddress
* @return {bool} true false
*/
#define FT_UART_IsTransmitFull(BaseAddress) ((Ft_in32(BaseAddress + UARTFTR_OFFSET) & (u32)UARTFTR_TXFF) == UARTFTR_TXFF)
void FUart_SendByte(u32 BaseAddress, u8 Byte);
u8 FUart_RecvByte(u32 BaseAddress);
u8 FUart_GetChar(u32 BaseAddress);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,196 @@
/*
 * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
 *
 * SPDX-License-Identifier: Apache-2.0.
 *
* @Date: 2021-04-07 09:53:07
* @LastEditTime: 2021-05-25 16:49:42
* @Description:  This files is for uart irq functions
*
* @Modify History:
* Ver   Who        Date         Changes
* ----- ------     --------    --------------------------------------
*/
#include "ft_uart.h"
extern u32 FUart_SendBuffer(Ft_Uart *UartPtr);
extern u32 FUart_ReceiveBuffer(Ft_Uart *UartPtr);
static void FUart_receiveErrorHandler(Ft_Uart *UartPtr, u32 InterruptStatus);
static void FUart_receiveDataHandler(Ft_Uart *UartPtr);
static void FUart_receiveTimeoutHandler(Ft_Uart *UartPtr);
static void FUart_sendDataHandler(Ft_Uart *UartPtr, u32 InterruptStatus);
/**
* @name: FUart_GetInterruptMask
* @msg: mask
* @param {Ft_Uart} *UartPtr
* @return {u32} mask
*/
u32 FUart_GetInterruptMask(Ft_Uart *UartPtr)
{
Ft_assertNonvoid(UartPtr != NULL);
return FT_UART_ReadReg(UartPtr->Config.BaseAddress, UARTIMSC_OFFSET);
}
void FUart_SetInterruptMask(Ft_Uart *UartPtr, u32 Mask)
{
u32 TempMask = Mask;
Ft_assertVoid(UartPtr != NULL);
TempMask &= UARTIMSC_ALLM;
FT_UART_WriteReg(UartPtr->Config.BaseAddress, UARTIMSC_OFFSET, TempMask);
}
/**
* @name: FUart_SetHandler
* @msg:
* @param {*}
* @return {*}
*/
void FUart_SetHandler(Ft_Uart *UartPtr, FUart_Handler_t FuncPtr,
void *Args)
{
Ft_assertVoid(UartPtr != NULL);
Ft_assertVoid(FuncPtr != NULL);
Ft_assertVoid(UartPtr->IsReady == FT_COMPONENT_IS_READLY);
UartPtr->Handler = FuncPtr;
UartPtr->Args = Args;
}
/**
* @name: FUart_InterruptHandler
* @msg:
* @param {Ft_Uart} *UartPtr
* @return {*}
*/
void FUart_InterruptHandler(Ft_Uart *UartPtr)
{
u32 RegValue = 0;
Ft_assertVoid(UartPtr != NULL);
Ft_assertVoid(UartPtr->IsReady == FT_COMPONENT_IS_READLY);
//Ft_printf("FUart_InterruptHandler %x\r\n", UartPtr);
RegValue = FT_UART_ReadReg(UartPtr->Config.BaseAddress, UARTIMSC_OFFSET);
RegValue &= FT_UART_ReadReg(UartPtr->Config.BaseAddress, UARTMIS_OFFSET);
if ((RegValue & ((u32)UARTMIS_RXMIS)) != (u32)0)
{
/* Received data interrupt */
FUart_receiveDataHandler(UartPtr);
}
if ((RegValue & ((u32)UARTMIS_TXMIS)) != (u32)0)
{
/* Transmit data interrupt */
FUart_sendDataHandler(UartPtr, RegValue);
}
if (((RegValue) & ((u32)UARTMIS_OEMIS | (u32)UARTMIS_BEMIS | (u32)UARTMIS_PEMIS | (u32)UARTMIS_FEMIS)) != (u32)0)
{
/* Received Error Status interrupt */
FUart_receiveErrorHandler(UartPtr, RegValue);
}
if ((RegValue & ((u32)UARTMIS_RTMIS)) != (u32)0)
{
/* Received Timeout interrupt */
FUart_receiveTimeoutHandler(UartPtr);
}
if (((RegValue) & ((u32)UARTMIS_DSRMMIS | (u32)UARTMIS_DCDMMIS | (u32)UARTMIS_CTSMMIS | (u32)UARTMIS_RIMMIS)) != (u32)0)
{
/* Modem status interrupt */
}
/* Clear the interrupt status. */
FT_UART_WriteReg(UartPtr->Config.BaseAddress, UARTICR_OFFSET,
RegValue);
}
static void FUart_receiveErrorHandler(Ft_Uart *UartPtr, u32 InterruptStatus)
{
UartPtr->rxbs_error = 0;
if (((InterruptStatus) & ((u32)UARTMIS_OEMIS | (u32)UARTMIS_BEMIS | (u32)UARTMIS_PEMIS | (u32)UARTMIS_FEMIS)) != 0)
{
UartPtr->rxbs_error = 1;
}
(void)FUart_ReceiveBuffer(UartPtr);
if (0 == UartPtr->rxbs_error)
{
if (UartPtr->Handler)
{
UartPtr->Handler(UartPtr->Args, FUART_EVENT_RECV_ERROR, UartPtr->ReceiveBuffer.RequestedBytes - UartPtr->ReceiveBuffer.RemainingBytes);
}
}
}
static void FUart_receiveDataHandler(Ft_Uart *UartPtr)
{
if ((u32)0 != UartPtr->ReceiveBuffer.RemainingBytes)
{
(void)FUart_ReceiveBuffer(UartPtr);
}
if ((u32)0 == UartPtr->ReceiveBuffer.RemainingBytes)
{
if (UartPtr->Handler)
{
UartPtr->Handler(UartPtr->Args, FUART_EVENT_RECV_DATA, UartPtr->ReceiveBuffer.RequestedBytes - UartPtr->ReceiveBuffer.RemainingBytes);
}
}
}
static void FUart_receiveTimeoutHandler(Ft_Uart *UartPtr)
{
u32 Event;
if ((u32)0 != UartPtr->ReceiveBuffer.RemainingBytes)
{
(void)FUart_ReceiveBuffer(UartPtr);
}
if ((u32)0 == UartPtr->ReceiveBuffer.RemainingBytes)
{
Event = FUART_EVENT_RECV_TOUT;
}
else
{
Event = FUART_EVENT_RECV_DATA;
}
if (UartPtr->Handler)
{
UartPtr->Handler(UartPtr->Args, Event, UartPtr->ReceiveBuffer.RequestedBytes - UartPtr->ReceiveBuffer.RemainingBytes);
}
}
static void FUart_sendDataHandler(Ft_Uart *UartPtr, u32 InterruptStatus)
{
u32 RegValue;
if (UartPtr->SendBuffer.RemainingBytes == (u32)0)
{
//<! close send isr
RegValue = FT_UART_ReadReg(UartPtr->Config.BaseAddress, UARTIMSC_OFFSET);
RegValue &= ~UARTIMSC_TXIM;
FT_UART_WriteReg(UartPtr->Config.BaseAddress, UARTIMSC_OFFSET, RegValue);
if (UartPtr->Handler)
{
UartPtr->Handler(UartPtr->Args, FUART_EVENT_RECV_DATA, UartPtr->ReceiveBuffer.RequestedBytes - UartPtr->ReceiveBuffer.RemainingBytes);
}
}
else if (InterruptStatus & UARTMIS_TXMIS)
{
FUart_SendBuffer(UartPtr);
}
else
{
}
}

View File

@ -0,0 +1,102 @@
/*
 * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
 *
 * SPDX-License-Identifier: Apache-2.0.
 *
* @Date: 2021-04-07 09:53:07
* @LastEditTime: 2021-05-24 10:47:33
* @Description:  This files is for uart option setting
*
* @Modify History:
* Ver   Who        Date         Changes
* ----- ------     --------    --------------------------------------
*/
#include "ft_uart.h"
#include "ft_uart_hw.h"
#include "ft_types.h"
/************************** Variable Definitions ****************************/
/*
* The following data type is a map from an option to the offset in the
* register to which it belongs as well as its bit mask in that register.
*/
typedef struct
{
u32 Option;
u32 RegisterOffset;
u32 Mask;
} Mapping;
static Mapping OptionTable[] = {
{FUART_OPTION_UARTEN, UARTCR_OFFSET, UARTCR_UARTEN},
{FUART_OPTION_RXEN, UARTCR_OFFSET, UARTCR_RXE},
{FUART_OPTION_TXEN, UARTCR_OFFSET, UARTCR_TXE},
{FUART_OPTION_FIFOEN, UARTLCR_H_OFFSET, UARTLCR_H_FEN}};
#define FT_UART_NUM_OPITIONS (sizeof(OptionTable) / sizeof(Mapping))
void FUart_SetOptions(Ft_Uart *UartPtr, u32 Options)
{
u32 Index;
u32 RegValue;
Ft_assertVoid(UartPtr != NULL);
Ft_assertVoid(UartPtr->IsReady == FT_COMPONENT_IS_READLY);
for (Index = 0; Index < FT_UART_NUM_OPITIONS; Index++)
{
RegValue = FT_UART_ReadReg(UartPtr->Config.BaseAddress, OptionTable[Index].RegisterOffset);
if ((Options & OptionTable[Index].Option) != (u32)(0))
{
RegValue |= OptionTable[Index].Mask;
}
else
{
RegValue &= ~OptionTable[Index].Mask;
}
FT_UART_WriteReg(UartPtr->Config.BaseAddress, OptionTable[Index].RegisterOffset, RegValue);
}
}
void FUart_SetSpecificOptions(Ft_Uart *UartPtr, u32 Options)
{
u32 Index;
u32 RegValue;
Ft_assertVoid(UartPtr != NULL);
for (Index = 0; Index < FT_UART_NUM_OPITIONS; Index++)
{
if ((Options & OptionTable[Index].Option) == (u32)(0))
{
continue;
}
RegValue = FT_UART_ReadReg(UartPtr->Config.BaseAddress, OptionTable[Index].RegisterOffset);
/* set specific options */
RegValue |= OptionTable[Index].Mask;
FT_UART_WriteReg(UartPtr->Config.BaseAddress, OptionTable[Index].RegisterOffset, RegValue);
}
}
void FUart_ClearSpecificOptions(FT_IN Ft_Uart *UartPtr, FT_IN u32 Options)
{
u32 Index;
u32 RegValue;
Ft_assertVoid(UartPtr != NULL);
for (Index = 0; Index < FT_UART_NUM_OPITIONS; Index++)
{
if ((Options & OptionTable[Index].Option) == (u32)(0))
{
continue;
}
RegValue = FT_UART_ReadReg(UartPtr->Config.BaseAddress, OptionTable[Index].RegisterOffset);
/* remove specific options */
RegValue &= ~OptionTable[Index].Mask;
FT_UART_WriteReg(UartPtr->Config.BaseAddress, OptionTable[Index].RegisterOffset, RegValue);
}
}

View File

@ -0,0 +1,13 @@
/*
 * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
 *
 * SPDX-License-Identifier: Apache-2.0.
 *
* @Date: 2021-04-07 09:53:07
* @LastEditTime: 2021-04-07 13:44:41
* @Description:  This files is for uart test cases
*
* @Modify History:
* Ver   Who        Date         Changes
* ----- ------     --------    --------------------------------------
*/

View File

@ -0,0 +1,41 @@
/*
 * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
 *
 * SPDX-License-Identifier: Apache-2.0.
 *
* @Date: 2021-04-07 09:53:07
* @LastEditTime: 2021-04-07 13:44:56
* @Description:  This files is for uart static init
*
* @Modify History:
* Ver   Who        Date         Changes
* ----- ------     --------    --------------------------------------
*/
#include "ft_uart.h"
#include "ft_parameters.h"
extern FUart_Config_t FUart_Config_tTable[FT_UART_NUM];
/**
* @name: Ft_Uart_LookupConfig
* @msg:
* @param {u16} InstanceId FT_UARTX_ID
* @return {*}
*/
FUart_Config_t *FUart_LookupConfig(u32 InstanceId)
{
FUart_Config_t *CfgPtr = NULL;
u32 Index;
for (Index = 0; Index < (u32)FT_UART_NUM; Index++)
{
if (FUart_Config_tTable[Index].InstanceId == InstanceId)
{
CfgPtr = &FUart_Config_tTable[Index];
break;
}
}
return (FUart_Config_t *)CfgPtr;
}

View File

@ -0,0 +1,180 @@
/*
 * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
 *
 * SPDX-License-Identifier: Apache-2.0.
 *
* Date: 2021-03-30 14:57:03
* @LastEditTime: 2021-05-24 14:35:00
* Description:  definitions of BSP parameters
* Modify History:
* * * Ver Who Date Changes
* * ----- ------ -------- ----------------------------------------------
* 1.00 Huanghe 2021/3/1 init
*/
#ifndef FT_PARAMETERS_H
#define FT_PARAMETERS_H
/* Device register address */
#define FT_DEV_BASE_ADDR 0x28000000
#define FT_DEV_END_ADDR 0x2FFFFFFF
/******** UART ************/
#define FT_UART_NUM 4
#define FT_UART_REG_LENGTH 0x18000
#define FT_UART0_ID 0
#define FT_UART0_BASE_ADDR 0x28000000
#define FT_UART0_CLK_FREQ_HZ 48000000
#define FT_UART1_ID 1
#define FT_UART1_BASE_ADDR 0x28001000
#define FT_UART1_CLK_FREQ_HZ 48000000
#define FT_UART2_ID 2
#define FT_UART2_BASE_ADDR 0x28002000
#define FT_UART2_CLK_FREQ_HZ 48000000
#define FT_UART3_BASE_ADDR 0x28003000
#define FT_UART3_ID 3
#define FT_UART3_CLK_FREQ_HZ 48000000
#define FT_STDOUT_BASEADDRESS FT_UART1_BASE_ADDR
#define FT_STDIN_BASEADDRESS FT_UART1_BASE_ADDR
/****** GIC v3 *****/
#define FT_GICV3_INSTANCES_NUM 1U
#define GICV3_REG_LENGTH 0x00009000
/*
* The maximum priority value that can be used in the GIC.
*/
#define GICV3_MAX_INTR_PRIO_VAL 240U
#define GICV3_INTR_PRIO_MASK 0x000000f0U
#define ARM_GIC_IPI_COUNT 16 /* MPCore IPI count */
#define SGI_INT_MAX 16
#define SPI_START_INT_NUM 32 /* SPI start at ID32 */
#define PPI_START_INT_NUM 16 /* PPI start at ID16 */
#define GIC_INT_MAX_NUM 1020 /* GIC max interrupts count */
#define FT_GICV3_BASEADDRESS 0x29900000U
#define FT_GICV3_DISTRIBUTOR_BASEADDRESS (FT_GICV3_BASEADDRESS + 0)
#define FT_GICV3_RD_BASEADDRESS (FT_GICV3_BASEADDRESS + 0x80000U)
#define FT_GICV3_SGI_BASEADDRESS (FT_GICV3_RD_BASEADDRESS + (1U << 16))
#define FT_GICV3_VECTORTABLE_NUM GIC_INT_MAX_NUM
/** Gmac **/
#define FT_GMAC_INSTANCES_NUM 2U
#define FT_GMAC_REG_LENGTH 0x00009000
#define FT_GMAC_COMMON_ADDR 0x2820B000U
#define FT_GMAC0_ID 0
#define FT_GMAC0_BASEADDR 0x2820C000U
#define FT_GMAC0_DEFAULT_ADDR \
{ \
0x11, 0x1c, 0x2c, 0x5c, 0x66, 0x88 \
}
#define FT_GMAC1_ID 1
#define FT_GMAC1_BASEADDR 0x28210000U
/** @defgroup ENET_Buffers_setting
* @{
*/
#define GMAC_MAX_PACKET_SIZE 1600 /* GMAC_HEADER + GMAC_EXTRA + VLAN_TAG + MAX_GMAC_PAYLOAD + GMAC_CRC */
#define GMAC_HEADER 14 /* 6 byte Dest addr, 6 byte Src addr, 2 byte length/type */
#define GMAC_CRC 4 /* Gmac CRC */
#define GMAC_EXTRA 2 /* Extra bytes in some cases */
#define VLAN_TAG 4 /* optional 802.1q VLAN Tag */
#define MIN_GMAC_PAYLOAD 46 /* Minimum Gmac payload size */
#define MAX_GMAC_PAYLOAD 1500 /* Maximum Gmac payload size */
#define JUMBO_FRAME_PAYLOAD 9000 /* Jumbo frame payload size */
#define RX_DESCNUM 1024U /* Rx buffers of size GMAC_MAX_PACKET_SIZE */
#define TX_DESCNUM 1024U /* Tx buffers of size GMAC_MAX_PACKET_SIZE */
#define PHY_USING_AR8035
#define GMAC0_ISRNUM 81
#define GMAC0_ISRPRIORITY 0
#define GMAC1_ISRNUM 82
#define GMAC1_ISRPRIORITY 0
/* SDC */
#define FT_SDC_NUM 1
#define FT_SDC_INSTANCE 0
#define FT_SDC_BASEADDR 0x28207C00U
#define FT_SDC_REG_LENGTH 0x4000
#define FT_SDC_FREQ 600000000
/* pin MUX/DEMUX */
#define FT_PIN_MUX_BASEADDR 0x28180000
#define FT_PIN_MUX_REG_LENGTH 0x10000
/* CAN */
#define FT_CAN_NUM 3
#define FT_CAN_REG_LENGTH 0x1000
#define FT_CAN0_BASEADDR 0x28207000
#define FT_CAN1_BASEADDR 0x28207400
#define FT_CAN2_BASEADDR 0x28207800
#define FT_CAN0_IRQNUM 119
#define FT_CAN1_IRQNUM 123
#define FT_CAN2_IRQNUM 124
#define FT_CAN_BAUDRATE 1000000 /* 1M */
#define FT_CAN_CLK 600000000
/* pci */
#define FT_PCI_CONFIG_BASEADDR 0x40000000
#define FT_PCI_CONFIG_REG_LENGTH 0x10000000
#define FT_PCI_IO_CONFIG_BASEADDR 0x50000000
#define FT_PCI_IO_CONFIG_REG_LENGTH 0x08000000
#define FT_PCI_MEM32_BASEADDR 0x58000000
#define FT_PCI_MEM32_REG_LENGTH 0x27000000
/* qspi */
#define FT_QSPI_NUM 1U
#define FT_QSPI_INSTANCE 0
#define FT_QSPI_MAX_CS_NUM 4
#define FT_QSPI_BASEADDR 0x28014000
#define FT_QSPI_FLASH_CAP_4MB 0
#define FT_QSPI_FLASH_CAP_8MB 1
#define FT_QSPI_FLASH_CAP_16MB 2
#define FT_QSPI_FLASH_CAP_32MB 3
#define FT_QSPI_FLASH_CAP_64MB 4
#define FT_QSPI_FLASH_CAP_128MB 5
#define FT_QSPI_FLASH_CAP_256MB 6
#define FT_QSPI_ADDR_SEL_3 0
#define FT_QSPI_ADDR_SEL_4 1
#define FT_QSPI_SCK_DIV_128 0
#define FT_QSPI_SCK_DIV_2 1
#define FT_QSPI_SCK_DIV_4 2
#define FT_QSPI_SCK_DIV_8 3
#define FT_QSPI_SCK_DIV_16 4
#define FT_QSPI_SCK_DIV_32 5
#define FT_QSPI_SCK_DIV_64 6
#define FT_QSPI_TRANSFER_1_1_1 0
#define FT_QSPI_TRANSFER_1_1_2 1
#define FT_QSPI_TRANSFER_1_1_4 2
#define FT_QSPI_TRANSFER_1_2_2 3
#define FT_QSPI_TRANSFER_1_4_4 4
#define FT_QSPI_TRANSFER_2_2_2 5
#define FT_QSPI_TRANSFER_4_4_4 6
/* smp */
#define FT_SMP_EN
#endif // !

View File

@ -0,0 +1,43 @@
/*
 * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
 *
 * SPDX-License-Identifier: Apache-2.0.
 *
* @Date: 2021-04-07 09:53:07
* @LastEditTime: 2021-05-18 13:43:09
* @Description:  This files is for type definition
*
* @Modify History:
* Ver   Who        Date         Changes
* ----- ------     --------    --------------------------------------
*/
#include "ft_types.h"
#include "ft_assert.h"
/************* 全局变量 用于判断驱动是否出现断言 *****************/
u32 Ft_assertStatus;
/************** 断言是否需要无限等待1 等待0不等待 ******************/
s32 Ft_assertWait = 1;
/* 当断言发生时,将会调用此函数 */
static Ft_assertCallback Ft_assertCallbackRoutine = NULL;
/************************** Function Prototypes ******************************/
void Ft_assert(FT_IN char *File, s32 Line)
{
if (Ft_assertCallbackRoutine != NULL)
{
Ft_assertCallbackRoutine(File, Line);
}
while (Ft_assertWait != 0)
{
}
}
void Ft_assertSetCallBack(Ft_assertCallback Routine)
{
Ft_assertCallbackRoutine = Routine;
}

View File

@ -0,0 +1,154 @@
/*
 * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
 *
 * SPDX-License-Identifier: Apache-2.0.
 *
* @Date: 2021-04-07 09:53:07
* @LastEditTime: 2021-05-18 13:43:19
* @Description:  This files is for assert function
*
* @Modify History:
* Ver   Who        Date         Changes
* ----- ------     --------    --------------------------------------
*/
#ifndef Ft_assert_H
#define Ft_assert_H
#include "ft_types.h"
#ifdef __cplusplus
extern "C"
{
#endif
#define Fassert_NONE 0U
#define Fassert_OCCURRED 1U
extern u32 Ft_assertStatus;
extern s32 Ft_assertWait;
extern void Ft_assert(FT_IN char *File, s32 Line);
typedef void (*Ft_assertCallback)(FT_IN char *File, s32 Line);
/**
* @name: Ft_assertVoid
* @msg:
* @param {*}
* @return {*}
*/
#define Ft_assertVoid(Expression) \
{ \
if (Expression) \
{ \
Ft_assertStatus = Fassert_NONE; \
} \
else \
{ \
Ft_assert(__FILE__, __LINE__); \
Ft_assertStatus = Fassert_OCCURRED; \
return; \
} \
}
/**
* @name:
* @msg:
* @in param:
* @inout param:
* @out param:
* @return {*}
*/
#define Ft_assertBool(Expression) \
{ \
if (Expression) \
{ \
Ft_assertStatus = Fassert_NONE; \
} \
else \
{ \
Ft_assert(__FILE__, __LINE__); \
Ft_assertStatus = Fassert_OCCURRED; \
return FALSE; \
} \
}
/**
* @name: Ft_assertZeroNum
* @msg: 0
* @param {*}
* @return {*}
*/
#define Ft_assertZeroNum(Expression) \
{ \
if (Expression) \
{ \
Ft_assertStatus = Fassert_NONE; \
} \
else \
{ \
Ft_assert(__FILE__, __LINE__); \
Ft_assertStatus = Fassert_OCCURRED; \
return FST_ASSERT_RETURN; \
} \
}
/**
* @name: Ft_assertNonvoid
* @msg: FST_ASSERT_RETURN
* @param {*}
* @return {*}
*/
#define Ft_assertNonvoid(Expression) \
{ \
if (Expression) \
{ \
Ft_assertStatus = Fassert_NONE; \
} \
else \
{ \
Ft_assert(__FILE__, __LINE__); \
Ft_assertStatus = Fassert_OCCURRED; \
return FST_ASSERT_RETURN; \
} \
}
/**
* @name: Ft_assertNoneReturn
* @msg:
* @param {*}
* @return {*}
*/
#define Ft_assertNoneReturn(Expression) \
{ \
if (Expression) \
{ \
Ft_assertStatus = Fassert_NONE; \
} \
else \
{ \
Ft_assert(__FILE__, __LINE__); \
Ft_assertStatus = Fassert_OCCURRED; \
} \
}
#define Ft_assertVoidAlways() \
{ \
Ft_assert(__FILE__, __LINE__); \
Ft_assertStatus = Fassert_OCCURRED; \
return; \
}
#define Ft_assertNonvoidAlways() \
{ \
Ft_assert(__FILE__, __LINE__); \
Ft_assertStatus = Fassert_OCCURRED; \
return FST_ASSERT_RETURN; \
}
void Ft_assertSetCallBack(Ft_assertCallback routine);
#ifdef __cplusplus
}
#endif
#endif // !

View File

@ -0,0 +1,86 @@
/*
 * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
 *
 * SPDX-License-Identifier: Apache-2.0.
 *
* @Date: 2021-04-16 14:00:59
* @LastEditTime: 2021-04-16 16:07:27
* @Description:  This files is for
*
* @Modify History:
* Ver   Who        Date         Changes
* ----- ------     --------    --------------------------------------
*/
#include "ft_cache.h"
__STATIC_INLINE u32 FCache_cacheLineSize(void)
{
u32 ctr;
asm volatile("mrc p15, 0, %0, c0, c0, 1"
: "=r"(ctr));
return 4 << ((ctr >> 16) & 0xF);
}
void FCache_cpuDcacheInvalidate(void *addr, ft_base_t size)
{
u32 lineSize = FCache_cacheLineSize();
u32 startAddr = (u32)addr;
u32 endAddr = (u32)addr + size + lineSize - 1;
asm volatile("dmb" ::
: "memory");
startAddr &= ~(lineSize - 1);
endAddr &= ~(lineSize - 1);
while (startAddr < endAddr)
{
asm volatile("mcr p15, 0, %0, c7, c6, 1" ::"r"(startAddr)); /* dcimvac */
startAddr += lineSize;
}
asm volatile("dsb" ::
: "memory");
}
void FCache_cpuDcacheClean(void *addr, ft_base_t size)
{
u32 lineSize = FCache_cacheLineSize();
u32 startAddr = (u32)addr;
u32 endAddr = (u32)addr + size + lineSize - 1;
asm volatile("dmb" ::
: "memory");
startAddr &= ~(lineSize - 1);
endAddr &= ~(lineSize - 1);
while (startAddr < endAddr)
{
asm volatile("mcr p15, 0, %0, c7, c10, 1" ::"r"(startAddr)); /* dccmvac */
startAddr += lineSize;
}
asm volatile("dsb" ::
: "memory");
}
void FCache_cpuIcacheInvalidate(void *addr, ft_base_t size)
{
u32 lineSize = FCache_cacheLineSize();
u32 startAddr = (u32)addr;
u32 endAddr = (u32)addr + size + lineSize - 1;
asm volatile("dmb" ::
: "memory");
startAddr &= ~(lineSize - 1);
endAddr &= ~(lineSize - 1);
while (startAddr < endAddr)
{
asm volatile("mcr p15, 0, %0, c7, c5, 1" ::"r"(startAddr)); /* icimvau */
startAddr += lineSize;
}
asm volatile("dsb\n\tisb" ::
: "memory");
}

View File

@ -0,0 +1,32 @@
/*
 * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
 *
 * SPDX-License-Identifier: Apache-2.0.
*
* @Date: 2021-04-13 21:52:20
* @LastEditTime: 2021-04-13 21:52:20
* @Description:  Description of file
* @Modify History:
* * * Ver   Who        Date         Changes
* * ----- ------     --------    --------------------------------------
*/
#ifndef FT_CACHE_H
#define FT_CACHE_H
#include "ft_types.h"
#ifdef __cplusplus
extern "C"
{
#endif
void FCache_cpuDcacheInvalidate(void *addr, ft_base_t size);
void FCache_cpuDcacheClean(void *addr, ft_base_t size);
void FCache_cpuIcacheInvalidate(void *addr, ft_base_t size);
#ifdef __cplusplus
}
#endif
#endif // !FT_CACHE_H

View File

@ -0,0 +1,145 @@
/*
 * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
 *
 * SPDX-License-Identifier: Apache-2.0.
*
* @Date: 2021-04-20 11:32:32
* @LastEditTime: 2021-05-25 10:51:19
* @Description:  Description of file
* @Modify History:
* * * Ver   Who        Date         Changes
* * ----- ------     --------    --------------------------------------
*/
#include "ft_parameters.h"
#include "ft_cpu.h"
#include "ft_assert.h"
#include "ft_printf.h"
#ifdef FT_SMP_EN
typedef union
{
u32 Slock;
struct ArchTicket
{
u16 owner;
u16 next;
} Tickets;
} FCpu_Lock_t;
struct FCpu
{
u32 IsReady;
FCpu_Lock_t Clock;
};
struct FCpu FCpu_Lock = {0};
const u32 SoftAffiTable[4] = {0, 1, 0x100, 0x101};
/**
* @name: FCpu_IdGet
* @msg: In a multiprocessor system, provides an additional PE identification mechanism for scheduling
purposes.
* @return {Aff0} Affinity level 0. The most significant affinity level field, for this PE in the system.
*/
s32 FCpu_IdGet(void)
{
s32 cpu_id;
__asm__ volatile(
"mrc p15, 0, %0, c0, c0, 5"
: "=r"(cpu_id));
// Ft_printf("error cpu_id %x \r\n", cpu_id);
// cpu_id &= 0xf;
switch ((cpu_id & 0xfff))
{
case 1:
return 1;
case 0x100:
return 2;
case 0x101:
return 3;
default:
return (cpu_id & 0xf);
}
}
s32 FCpu_AffinityGet(void)
{
s32 AffinityId;
__asm__ volatile(
"mrc p15, 0, %0, c0, c0, 5"
: "=r"(AffinityId));
return AffinityId & 0xfff;
}
void FCpu_SpinLockInit(void)
{
FCpu_Lock.Clock.Slock = 0;
FCpu_Lock.IsReady = FT_COMPONENT_IS_READLY;
}
void FCpu_SpinLock(void)
{
u32 Tmp;
u32 Newval;
FCpu_Lock_t LockVal;
Ft_assertVoid(FCpu_Lock.IsReady == FT_COMPONENT_IS_READLY);
__asm__ __volatile__(
"pld [%0]" ::"r"(&FCpu_Lock.Clock.Slock));
__asm__ __volatile__(
"1: ldrex %0, [%3]\n"
" add %1, %0, %4\n"
" strex %2, %1, [%3]\n"
" teq %2, #0\n"
" bne 1b"
: "=&r"(LockVal), "=&r"(Newval), "=&r"(Tmp)
: "r"(&FCpu_Lock.Clock.Slock), "I"(1 << 16)
: "cc");
while (LockVal.Tickets.next != LockVal.Tickets.owner)
{
__asm__ __volatile__("wfe" ::
: "memory");
LockVal.Tickets.owner = *(volatile unsigned short *)(&FCpu_Lock.Clock.Tickets.owner);
}
__asm__ volatile("dmb" ::
: "memory");
}
void FCpu_SpinUnlock(void)
{
Ft_assertVoid(FCpu_Lock.IsReady == FT_COMPONENT_IS_READLY);
__asm__ volatile("dmb" ::
: "memory");
FCpu_Lock.Clock.Tickets.owner++;
__asm__ volatile("dsb ishst\nsev" ::
: "memory");
}
#else /*RT_USING_SMP*/
s32 FCpu_IdGet(void)
{
return 0;
}
void FCpu_SpinLockInit(void)
{
return;
}
void FCpu_SpinLock(void)
{
return;
}
void FCpu_SpinUnlock(void)
{
return;
}
#endif

View File

@ -0,0 +1,26 @@
/*
 * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
 *
 * SPDX-License-Identifier: Apache-2.0.
*
* @Date: 2021-04-20 11:33:54
* @LastEditTime: 2021-04-20 11:33:55
* @Description:  Description of file
* @Modify History:
* * * Ver   Who        Date         Changes
* * ----- ------     --------    --------------------------------------
*/
#ifndef FT_CPU_H
#define FT_CPU_H
#include "ft_types.h"
#include "ft_error_code.h"
extern const u32 SoftAffiTable[4];
s32 FCpu_IdGet(void);
void FCpu_SpinLockInit(void);
void FCpu_SpinLock(void);
void FCpu_SpinUnlock(void);
s32 FCpu_AffinityGet(void);
#endif // !FT_SPIN_H

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